2009-05-29 8 views
5

Tengo un procedimiento almacenado con varias instrucciones de inserción/selección. Digamos que estoy usando la primera inserción para completar una tabla de "Administrador". En la inserción, se agrega un ManagerId (incrementado automáticamente), pero no se hace referencia en la instrucción de inserción. Luego deseo utilizar el ID de administrador de esta tabla para insertar una fila en otra tabla, donde ID de administrador es una clave externa. Código de ejemplo como sigue ..Recuperación del valor de la columna autoincrementado de la tabla donde se inserta/selecciona múltiples en el procedimiento almacenado único

USE [TEST] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[sptInsertNewManager] 
    -- Add the parameters for the stored procedure here 
    @FName varchar(50), 
    @LName varchar(50), 
    @EMail varchar(100), 
    @UserRoleID int, 
    @LANUserID varchar(25), 
    @GroupID int 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    -- Insert statements for procedure here 
INSERT INTO [Manager]   
      ([FName], 
      [LName], 
      [Email], 
      [UserRoleID], 
      [LANUserID],   
      [ActiveFlag], 
      [GroupID] 
) 
    VALUES 
      (@FName 
      ,@LName 
      ,@EMail 
      ,@UserRoleID 
      ,@LANUserID 
      ,1 
      ,@GroupID); 

COMMIT 

SELECT ManagerId FROM [Manager] AS newManager WHERE LANUserID = @LANUserID; 
     --also insert into Users table. 
    INSERT INTO [dbo].[aspnet_Users] (
     [UserId], 
     [UserName], 
     [LoweredUserName], 
     [ManagerId] 
    ) 
     VALUES (
      NEWID(), 
      @LANUserID, 
      LOWER(@LANUserID), 
      newManager) 
END 

Esto, obviamente, no funciona. Este fue mi intento de resolver esto. Soy bastante nuevo en SQL, por lo que cualquier ayuda con este problema sería muy apreciada.

Respuesta

7

uso SCOPE_IDENTITY() después de su inserción para capturar el valor más reciente sola identidad desde dentro de su alcance actual:

DECLARE @ID  int 


INSERT ...... 
SELECT @ID=scope_identity() 

uso @ID siempre que lo necesite

nota: SCOPE_IDENTITY() se prefiere sobre la @@ IDENTIDAD más antigua porque proporciona el último valor de Identidad en el alcance actual, lo que evita los problemas de los desencadenantes que se insertan en las tablas de registro (con identidades).

Sin embargo, si necesita varios valores de identidad (inserción de un conjunto de filas), y utilizar la salida EN:

declare @test table (RowID int identity(1,1) primary key not null, RowValue varchar(10) null) 
declare @OutputTable table (RowID int not null) 

insert into @test (RowValue) 
    OUTPUT INSERTED.RowID 
    INTO @OutputTable 
    SELECT 'A' 
    UNION SELECT 'B' 
    UNION SELECT 'C' 
    UNION SELECT 'D' 
    UNION SELECT 'E' 


select * from @OutputTable 

la salida:

(5 row(s) affected) 
RowID 
----------- 
1 
2 
3 
4 
5 

(5 row(s) affected) 
0

Puede utilizar @@ identidad variable global para recuperar el último valor de identidad insertado

SELECT @[email protected]@Identity 

también puede usar Scope_Identity e IDENT_ funciones actuales

+1

@@ dentity le dará la última identidad, incluso si no era de el inserto en su alcance (como si el inserto dispara un disparador) –

+0

De acuerdo con KM, nunca usaría @@ identity porque tarde o temprano tendrá problemas de integridad de datos. SAme con ident_current (puede obtener la identidad de otro proceso que acaba de insertar después del suyo). Si quiero la identidad que acabo de insertar, uso scope_identity o en una versión más nueva puedes usar la cláusula de salida (no estoy seguro si esto entró en 2005 o 2008, ya que saltamos 2005) que tiene la ventaja de devolver todo el conjunto de identidad valores si ejecutó un inserto de registro mulitple basado en conjunto. – HLGEM

2

para MS SQL Server

Cada vez que inserte un disco y tiene la columna de incremento automático (columna de identidad en MS-SQL con el lenguaje) se puede usuario de este para recuperar el id de la fila que insertó:

@id = SCOPE_IDENTITY() 

esto asegura que se obtiene el valor de columna de identidad que produce su inserción, no por los demás usuarios durante el tiempo de su código se ejecuta (entre el inserto y obtener la identidad de SCOPE_IDENTITY())

2

Yuck ... usted tiene su proc y transacción completamente torcido ...

desea que estos dos insertos que se produzca en la misma transacción (que estoy deduciendo de la declaración COMMIT en medio de su proc originales) . Por lo tanto, debe colocar correctamente una declaración BEGIN TRANSACTION y COMMIT en todas sus declaraciones INSERT y SELECT para aislar el cambio de datos.

considerar lo siguiente:

CREATE PROCEDURE [dbo].[sptInsertNewManager] 
    -- Add the parameters for the stored procedure here 
    @FName varchar(50), 
    @LName varchar(50), 
    @EMail varchar(100), 
    @UserRoleID int, 
    @LANUserID varchar(25), 
    @GroupID int 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

DECLARE @ManagerID INT 

BEGIN TRANSACTION  

    -- Insert statements for procedure here 
INSERT INTO [Manager]   
      ([FName], 
      [LName], 
      [Email],  
      [UserRoleID], 
      [LANUserID],   
      [ActiveFlag], 
      [GroupID] 
) 
    VALUES 
       (@FName 
       ,@LName 
       ,@EMail 
      ,@UserRoleID 
      ,@LANUserID 
       ,1 
      ,@GroupID); 

-- Collect the ID you just created 
SELECT @ManagerID = SCOPE_IDENTITY() 


     --also insert into Users table. 
    INSERT INTO [dbo].[aspnet_Users] (
     [UserId], 
     [UserName], 
     [LoweredUserName], 
     [ManagerId] 
    ) 
     VALUES (
       NEWID(), 
       @LANUserID, 
       LOWER(@LANUserID), 
       @ManagerID) -- This is the new identity you just created 

COMMIT 

END 
1

Asimismo, no se comprometen en el medio de la transacción, se desea que ambas inserciones de revertir si uno falla. Lea en libros en línea sobre el procesamiento de transacciones.

1

podemos volver la columna de identidad como:

SELECT @@identity as 'Identity' 

y leer este valor de identidad de código como:

int ID = Convert.ToInt32(cmdinsert.ExecuteScalar()); 
Cuestiones relacionadas