2009-05-29 9 views
5

Mam procedurę składowaną z wieloma instrukcjami wstawiania/wyboru. Powiedzmy, że używam pierwszego insertu do wypełnienia tabeli "Manager". Przy wstawianiu dodawany jest identyfikator menedżera (zwiększany automatycznie), ale nie wymieniony w instrukcji wstawiania. Następnie chcę użyć Identyfikator Manager z tej tabeli, aby wstawić wiersz do innej tabeli, gdzie ManagerId jest kluczem obcym. Przykładowy kod:Trwa pobieranie automatycznie zwiększanej wartości kolumny z tabeli, w której wielokrotne wstawianie/wybieranie w pojedynczej przechowywanej procedurze

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 

To oczywiście nie działa. To była moja próba rozwiązania tego. Jestem całkiem nowy w SQL, więc każda pomoc w tym problemie byłaby bardzo doceniana.

Odpowiedz

7

użycie SCOPE_IDENTITY() po wkładce do przechwytywania najnowszą wartość pojedynczej tożsamości z poziomu bieżącego zakresu:

DECLARE @ID  int 


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

użycie @ID gdziekolwiek jest to potrzebne

UWAGA: SCOPE_IDENTITY() jest korzystne przez starszą @@ TOŻSAMOŚĆ, ponieważ podaje ostatnią wartość Tożsamości w bieżącym zakresie, co pozwala uniknąć problemów z wyzwalaczami wstawiającymi do tabel dziennika (z tożsamościami).

Jednak jeśli trzeba wiele wartości tożsamości (wstawienie zbioru wierszy), użyj produktowej oraz na:

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 

wyjścia:

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

(5 row(s) affected) 
0

Można użyć zmiennej globalnej @@ Identity do pobrania ostatnio wstawionej wartości identyfikacyjnej:

SELECT @[email protected]@Identity 

można również użyć Scope_Identity i IDENT_ Aktualne funkcje

+1

@@ dentity daje ostatnią tożsamości, nawet jeśli nie było od wstawić w swoim zasięgu (np. jeśli wkładka uruchamia spust) –

+0

Zgadzam się z KM, nigdy nie użyłbym @@ tożsamości, ponieważ wcześniej czy później będziesz miał problemy z integralnością danych. SAme z ident_current (możesz uzyskać tożsamość innego procesu po prostu wstawionego po twoim). Jeśli chcę tożsamość, którą właśnie wstawiłem, używam scope_identity lub w nowszej wersji można użyć klauzuli output (nie jestem pewien, czy to przyszło w 2005 lub 2008 roku, gdy pominęliśmy 2005), co ma tę zaletę, że zwraca cały zestaw tożsamości wartości, jeśli uruchomiono opartą na zestawie wstawkę rekordu mulitple. – HLGEM

2

dla MS SQL Server

Kiedykolwiek wstawić rekord i ma kolumny automatycznego przyrostu (tożsamość kolumny w MS-SQL żargonie) można użytkownik tego, aby pobrać identyfikator dla wiersza wstawionego:

@id = SCOPE_IDENTITY() 

gwarantuje to uzyskać wartość kolumny tożsamości, że wkładka produkowane, a nie przez innych użytkowników w czasie Twój kod został uruchomiony (między wkładką a uzyskanie tożsamości przez SCOPE_IDENTITY())

2

Fuj ... masz swój proces i transakcję wykręconą ...

Chcesz, aby te dwie przekładki pojawiły się w ramach tej samej transakcji (co wyprowadzam z instrukcji COMMIT w środku twojego pierwotnego procesu) . Musisz więc odpowiednio umieścić oświadczenie BEGIN TRANSACTION i COMMIT wokół wszystkich swoich instrukcji INSERT i SELECT, aby wyizolować zmianę danych.

Rozważmy następujący:

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

również nie popełnić w trakcie transakcji, chcesz oba wkłady do wycofywania jeśli nie powiedzie się. Czytaj w Książkach online o przetwarzaniu transakcji.

1

Możemy powrócić kolumnę tożsamości takiego:

SELECT @@identity as 'Identity' 

i przeczytać tę wartość tożsamości w kodzie jak:

int ID = Convert.ToInt32(cmdinsert.ExecuteScalar()); 
Powiązane problemy