Najlepszy sposób na uzyskanie tożsamości wstawionego wiersza?

Jaki jest najlepszy sposób na uzyskanie IDENTITY wstawionego wiersza?

Wiem o @@IDENTITY i IDENT_CURRENT i SCOPE_IDENTITY} ale nie rozumiem za i przeciw związane z każdym.

Czy ktoś może wyjaśnić różnice i kiedy powinienem używać każdego z nich?

Author: DineshDB, 2008-09-04

11 answers

  • @@IDENTITY zwraca ostatnią wartość tożsamości wygenerowaną dla dowolnej tabeli w bieżącej sesji, we wszystkich zakresach. Musisz być ostrożna, ponieważ to jest w różnych zakresach. Możesz uzyskać wartość z wyzwalacza, zamiast bieżącego wyciągu.

  • SCOPE_IDENTITY() zwraca ostatnią wartość tożsamości wygenerowaną dla dowolnej tabeli w bieżącej sesji oraz bieżący zakres. ogólnie to, co chcesz użyj .

  • IDENT_CURRENT('tableName') zwraca ostatnią wartość tożsamości wygenerowaną dla określonej tabeli w dowolnej sesji i dowolnym zakresie. Pozwala to określić, z której tabeli chcesz uzyskać wartość, na wypadek, gdyby powyższe dwie nie były dokładnie tym, czego potrzebujesz ( Very rare ). Ponadto, jak wspomniał @ Guy Starbuck, "możesz użyć tego, jeśli chcesz uzyskać bieżącą wartość tożsamości dla tabeli, do której nie wstawiłeś rekordu."

  • Na OUTPUT klauzula of Instrukcja INSERT pozwoli ci uzyskać dostęp do każdego wiersza wstawionego za pomocą tej instrukcji. Ponieważ jest ona ograniczona do konkretnej instrukcji, jest ona bardziej prosta niż pozostałe funkcje powyżej. Jednak jest to trochę bardziej wyraziste (musisz wstawić do tabeli zmienną / tabelę temp,a następnie ją odpytywać) i daje wyniki nawet w scenariuszu błędu, w którym instrukcja jest wycofywana. To powiedziawszy, jeśli Twoje zapytanie używa równoległego planu wykonania, jest to tylko metoda gwarantowana do uzyskania tożsamości(brak wyłączenia równoległości). Jednak jest on wykonywany przed wyzwalaczami i nie może być użyty do zwracania wartości generowanych przez wyzwalacze.

 1202
Author: bdukes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:48

Uważam, że najbezpieczniejszą i najdokładniejszą metodą odzyskiwania wstawionego identyfikatora byłoby użycie klauzuli output.

Na przykład (zaczerpnięte z następującego artykułu MSDN )

USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table( NewScrapReasonID smallint,
                           Name varchar(50),
                           ModifiedDate datetime);
INSERT Production.ScrapReason
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
        INTO @MyTableVar
VALUES (N'Operator error', GETDATE());

--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate 
FROM Production.ScrapReason;
GO
 156
Author: Orry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-20 15:11:28

Mówię to samo co inni, więc wszyscy mają rację, staram się to wyjaśnić.

@@IDENTITY zwraca id ostatniej rzeczy, która została wstawiona przez połączenie klienta z bazą danych.
W większości przypadków działa to dobrze, ale czasami uruchamia się wyzwalacz i wstawia nowy wiersz, o którym nie wiesz, i otrzymasz ID z tego nowego wiersza, zamiast tego, który chcesz

SCOPE_IDENTITY() rozwiązuje ten problem. Zwraca id ostatniej rzeczy, która wstawiłeś w kodzie SQL wysłałeś do bazy danych. Jeśli wyzwalacze pójdą i utworzą dodatkowe wiersze, nie spowodują zwrócenia niewłaściwej wartości. Hurra

IDENT_CURRENT zwraca ostatni identyfikator, który został wstawiony przez kogokolwiek. Jeśli jakaś inna aplikacja zdarzy się wstawić inny wiersz w niewymuszonym czasie, otrzymasz ID tego wiersza zamiast Twojego.

Jeśli chcesz grać bezpiecznie, Zawsze używaj SCOPE_IDENTITY(). Jeśli zostaniesz przy @@IDENTITY i ktoś zdecyduje się dodać WYZWALACZ później, wszystkie Twój Kod się złamie.

 97
Author: Orion Edwards,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-03 21:44:50

Najlepszym (Czytaj: najbezpieczniejszym) sposobem uzyskania tożsamości nowo wstawionego wiersza jest użycie output klauzuli:

create table TableWithIdentity
           ( IdentityColumnName int identity(1, 1) not null primary key,
             ... )

-- type of this table's column must match the type of the
-- identity column of the table you'll be inserting into
declare @IdentityOutput table ( ID int )

insert TableWithIdentity
     ( ... )
output inserted.IdentityColumnName into @IdentityOutput
values
     ( ... )

select @IdentityValue = (select ID from @IdentityOutput)
 55
Author: Ian Kemp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-06 12:26:21

Dodaj

SELECT CAST(scope_identity() AS int);

Na koniec polecenia insert sql, następnie

NewId = command.ExecuteScalar()
/ Align = "left" /
 21
Author: Jim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-26 14:12:50

MSDN

@ @ IDENTITY, SCOPE_IDENTITY i IDENT_CURRENT są podobnymi funkcjami, ponieważ zwracają ostatnią wartość dodaną do kolumny IDENTITY tabeli.

@ @ IDENTITY i SCOPE_IDENTITY zwrócą ostatnią wartość tożsamości wygenerowaną w dowolnej tabeli w bieżącej sesji. Jednak SCOPE_IDENTITY Zwraca wartość tylko w bieżącym zakresie; @ @ IDENTITY nie jest ograniczone do określonego zakresu.

IDENT_CURRENT nie jest ograniczony zakresem i sesji; jest ona ograniczona do określonej tabeli. IDENT_CURRENT Zwraca wartość tożsamości wygenerowaną dla określonej tabeli w dowolnej sesji i dowolnym zakresie. Aby uzyskać więcej informacji, zobacz IDENT_CURRENT.

 12
Author: Jakub Šturc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-03 21:37:02

@@IDENTITY jest ostatnią tożsamością wstawioną przy użyciu bieżącego połączenia SQL. Jest to dobra wartość do powrotu z procedury składowanej insert, gdzie wystarczy wstawić tożsamość dla nowego rekordu i nie obchodzi cię, czy więcej wierszy zostało dodanych później.

SCOPE_IDENTITY jest ostatnią tożsamością wstawioną przy użyciu bieżącego połączenia SQL, a w bieżącym zakresie -- to znaczy, jeśli po wstawieniu była wstawiona druga tożsamość oparta na wyzwalaczu, nie być odzwierciedlone w SCOPE_IDENTITY, tylko insert, który wykonałeś. Szczerze mówiąc, nigdy nie miałem powodu, by tego użyć.

IDENT_CURRENT (tablename) jest ostatnią dodaną tożsamością niezależnie od połączenia lub zakresu. Możesz tego użyć, jeśli chcesz uzyskać bieżącą wartość tożsamości dla tabeli, do której nie wstawiono rekordu.

 12
Author: Guy Starbuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-10 21:23:44

Kiedy używasz struktury encji, wewnętrznie używa techniki OUTPUT, aby zwrócić nowo wstawioną wartość ID

DECLARE @generated_keys table([Id] uniqueidentifier)

INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
VALUES('Malleable logarithmic casing');

SELECT t.[TurboEncabulatorID ]
FROM @generated_keys AS g 
   JOIN dbo.TurboEncabulators AS t 
   ON g.Id = t.TurboEncabulatorID 
WHERE @@ROWCOUNT > 0

Wyniki wyjściowe są przechowywane w tymczasowej zmiennej table, połączone z powrotem do tabeli i zwracają wartość wiersza z tabeli.

Uwaga: Nie mam pojęcia, dlaczego EF połączy się wewnętrznie z efemeryczną tabelą z powrotem do prawdziwej tabeli (w jakich okolicznościach te dwie nie pasowałyby do siebie).

Ale To właśnie robi EF.

Ta technika (OUTPUT) jest tylko dostępne na SQL Server 2008 lub nowszym.

 11
Author: Ian Boyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-04 15:05:48

Zawsze używaj scope_identity (), nigdy nie ma potrzeby niczego innego.

 7
Author: erikkallen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-09 20:35:00

Nie mogę rozmawiać z innymi wersjami SQL Servera, ale w 2012, wyjście bezpośrednio działa dobrze. Nie musisz zawracać sobie głowy tymczasowym stołem.

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)

Nawiasem mówiąc, ta technika działa również podczas wstawiania wielu wierszy.

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
    (...),
    (...),
    (...)

Wyjście

ID
2
3
4
 5
Author: MarredCheese,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-06 16:58:15

Po Twojej wstawce musisz to dodać. I upewnij się, że nazwa tabeli, w której wstawiane są dane.Otrzymasz bieżący wiersz nr gdzie wiersz dotknięty właśnie teraz przez Twoją instrukcję insert.

IDENT_CURRENT('tableName')
 0
Author: Khan Ataur Rahman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 06:04:43