Jaka jest różnica między Scope_Identity (), Identity (), @@ Identity i Ident_Current ()?

192

Wiem Scope_Identity(), Identity(), @@Identity, i Ident_Current()wszyscy się wartość kolumny tożsamości, ale chciałbym, aby znać różnicę.

Częścią moich kontrowersji jest to, co rozumieją przez zakres w odniesieniu do powyższych funkcji?

Chciałbym również prosty przykład różnych scenariuszy ich używania?

Tebo
źródło
2
Nie zapomnij o błędzie równoległego wykonywania, który istnieje w SQL Server dla SCOPE_IDENTITY i @@ IDENTITY: support.microsoft.com/default.aspx?scid=kb;en-US;2019779
David d C e Freitas
@DaviddCeFreitas - Jestem ciekawy, czy mogę przeczytać o błędzie, ale link wydaje się być zepsuty (a przynajmniej powoduje błąd ASP).
rory.ap
2
Właściwie to znalazłem: support.microsoft.com/en-us/kb/2019779
rory.ap
Poprawka została wydana, jak wspomniano w starym artykule KB
George Birbilis

Odpowiedzi:

395
  • @@identityFunkcja zwraca ostatni tożsamości utworzony w tej samej sesji.
  • scope_identity()Funkcja zwraca ostatni tożsamości utworzony w tej samej sesji i tego samego zakresu.
  • ident_current(name)Zwraca ostatni tożsamość stworzoną dla konkretnej tabeli lub widoku w każdej sesji.
  • identity()Funkcja nie jest używana, aby uzyskać tożsamość, jest używany do tworzenia tożsamości w select...intozapytaniu.

Sesja jest połączeniem z bazą danych. Zakres jest bieżącym zapytaniem lub bieżącą procedurą składowaną.

Sytuacja, w której scope_identity()i @@identityfunkcje różnią się, to jeśli masz spust na stole. Jeśli masz zapytanie, które wstawia rekord, powodując, że wyzwalacz wstawi gdzieś inny rekord, scope_identity()funkcja zwróci tożsamość utworzoną przez zapytanie, a @@identityfunkcja zwróci tożsamość utworzoną przez wyzwalacz.

Więc normalnie użyłbyś tej scope_identity()funkcji.

Guffa
źródło
14
Wybrałem to jako odpowiedź ze względu na „Sytuację, w której scope_identity () i @@ tożsamość ...”. Wyjaśniło to bardziej.
Tebo,
1
Jak wspomniano powyżej David Freitas, w implementacji scope_identity występuje błąd, dlatego zalecam użycie alternatywnej metody, klauzula OUTPUT. Zobacz moją odpowiedź poniżej.
Sebastian Meine
@Guffa - „Sesja jest połączeniem z bazą danych”. Czy sesja jest utrzymywana między połączeniami, jeśli korzystasz z Pula połączeń?
Dave Black
1
To odpowiedź na wzór do naśladowania. W szczególności praca z SQL i SQL Server może być dziwna, a to wyjaśnia wszystko w bardzo jasny, laicki sposób, a jednocześnie jest dość informacyjny. To nie brzmi jak coś komunikowanego między dwoma specjalistami od baz danych, co robi Mnóstwo innych odpowiedzi SE.
Panzercrisis
@DaveBlack z tego, co przeczytałem: Nie, sesja nie jest utrzymywana w puli, sesja jest unikalna dla skryptu uruchamianego po connect (). Podczas pulowania ... PHP dla SQL Server używa puli połączeń ODBC. Gdy używane jest połączenie z puli, stan połączenia jest resetowany. Zamknięcie połączenia zwraca połączenie do puli. (uwaga: patrz uwagi do systemu Linux / Mac) docs.microsoft.com/en-us/sql/connect/php/…
GDmac
42

Dobre pytanie.

  • @@IDENTITY: zwraca ostatnią wartość tożsamości wygenerowaną dla połączenia SQL (SPID). Przez większość czasu będzie to, czego chcesz, ale czasami tak nie jest (na przykład, gdy wyzwalacz jest uruchamiany w odpowiedzi na INSERT, a wyzwalacz wykonuje inną INSERTinstrukcję).

  • SCOPE_IDENTITY(): zwraca ostatnią wartość tożsamości wygenerowaną w bieżącym zakresie (tj. procedura przechowywana, wyzwalacz, funkcja itp.).

  • IDENT_CURRENT(): zwraca ostatnią wartość tożsamości dla określonej tabeli. Nie używaj tego, aby uzyskać wartość tożsamości z INSERT, zależy to od warunków wyścigu (tj. Wiele połączeń wstawia wiersze na tym samym stole).

  • IDENTITY(): używane, gdy deklarujemy kolumnę w tabeli jako kolumnę tożsamości.

Więcej informacji można znaleźć na stronie: http://msdn.microsoft.com/en-us/library/ms187342.aspx .

Podsumowując: jeśli wstawianie wierszy, a chcesz poznać wartość kolumny tożsamości dla rzędu ty po prostu wstawiony, zawsze używać SCOPE_IDENTITY().

Brannon
źródło
16

Jeśli zrozumiesz różnicę między zakresem a sesją, zrozumienie tych metod będzie bardzo łatwe.

Bardzo ładny post na blogu autorstwa Adama Andersona opisuje tę różnicę:

Sesja oznacza bieżące połączenie, które wykonuje polecenie.

Zakres oznacza bezpośredni kontekst polecenia. Każde wywołanie procedury składowanej wykonuje się we własnym zakresie, a wywołania zagnieżdżone są wykonywane w zakresie zagnieżdżonym w zakresie procedury wywołującej. Podobnie polecenie SQL wykonane z aplikacji lub SSMS wykonuje się we własnym zakresie, a jeśli polecenie to uruchamia dowolne wyzwalacze, każdy wyzwalacz wykonuje się we własnym zakresie zagnieżdżonym.

Zatem różnice między trzema metodami wyszukiwania tożsamości są następujące:

@@identityzwraca ostatnią wartość tożsamości wygenerowaną w tej sesji, ale dowolny zakres.

scope_identity()zwraca ostatnią wartość tożsamości wygenerowaną w tej sesji i ten zakres.

ident_current()zwraca ostatnią wartość tożsamości wygenerowaną dla określonej tabeli w dowolnej sesji i dowolnym zakresie.

Hemant Sakta
źródło
11

Zakres oznacza kontekst kodu, który wykonuje INSERTinstrukcję SCOPE_IDENTITY(), w przeciwieństwie do globalnego zakresu @@IDENTITY.

CREATE TABLE Foo(
  ID INT IDENTITY(1,1),
  Dummy VARCHAR(100)
)

CREATE TABLE FooLog(
  ID INT IDENTITY(2,2),
  LogText VARCHAR(100)
)
go
CREATE TRIGGER InsertFoo ON Foo AFTER INSERT AS
BEGIN
  INSERT INTO FooLog (LogText) VALUES ('inserted Foo')
  INSERT INTO FooLog (LogText) SELECT Dummy FROM inserted
END

INSERT INTO Foo (Dummy) VALUES ('x')
SELECT SCOPE_IDENTITY(), @@IDENTITY 

Daje różne wyniki.

devio
źródło
9

Z powodu błędu wspomnianego przez @David Freitas oraz z powodu niezgodności z nową funkcją Sekwencji, która została wprowadzona w 2012 roku, polecam trzymać się z daleka od tych wszystkich trzech. Zamiast tego możesz użyć klauzuli OUTPUT, aby uzyskać wstawioną wartość tożsamości. Inną zaletą jest to, że WYJŚCIE działa nawet, jeśli wstawiono więcej niż jeden wiersz.

Szczegółowe informacje i przykłady można znaleźć tutaj: kryzys tożsamości

Sebastian Meine
źródło
Myślę, że ta odpowiedź zasługuje na większą uwagę.
cheeze
Niestety INSERT ... OUTPUT Inserted.xx nie działa z wyzwalaczami INSERT (to samo dotyczy UPDATE ... OUTPUT Updated.xx i wyzwalaczy UPDATE). Sugerują użycie INSERT ... OUTPUT INTO, ale jest to zbyt szczegółowe i używanie tego z klientów (zamiast w przechowywanych procesach) jest problematyczne. WSTAW ... WYJŚCIE Inserted.xx jest piękny, gdy jest używany z wywołaniami po stronie klienta (wystarczy wykonać ExecuteScalar, aby wstawić i powiedzieć odzyskać automatycznie wygenerowany identyfikator dla nowego wiersza), jeśli nie potrzebujesz wyzwalaczy.
George Birbilis,
Czy ten błąd został naprawiony? minęło 8 lat od napisania tego artykułu
dopatraman
6

Aby wyjaśnić problem z @@Identity:

Na przykład, jeśli wstawisz tabelę i ta tabela ma wyzwalacze wykonujące wstawki, @@Identityzwróci identyfikator z wstawki w wyzwalaczu (a log_idlub coś), a scope_identity()zwróci identyfikator z wstawki w oryginalnej tabeli.

Więc jeśli nie masz żadnych wyzwalaczy scope_identity()i @@identityzwróci tę samą wartość. Jeśli masz wyzwalacze, musisz pomyśleć o tym, jaką wartość chcesz.

Jonas Lincoln
źródło
4

Scope Identity: Tożsamość ostatniego rekordu dodanego w ramach wykonywanej procedury składowanej.

@@Identity: Tożsamość ostatniego rekordu dodanego w partii zapytania lub w wyniku zapytania, np. Procedura, która wykonuje wstawianie, a następnie uruchamia wyzwalacz, który następnie wstawia rekord, zwróci tożsamość wstawionego rekordu z wyzwalacza.

IdentCurrent: Ostatnia tożsamość przydzielona dla tabeli.

Andrzej
źródło
3

Oto kolejne dobre wyjaśnienie z książki :

Jeśli chodzi o różnicę między SCOPE_IDENTITY i @@ IDENTITY, załóżmy, że masz procedurę składowaną P1 z trzema instrukcjami:
- WSTAW, który generuje nową wartość tożsamości
- Wywołanie do procedury składowanej P2, która ma również instrukcję INSERT, która generuje nową wartość tożsamości
- Instrukcja, która wysyła zapytanie do funkcji SCOPE_IDENTITY i @@ IDENTITY Funkcja SCOPE_IDENTITY zwróci wartość wygenerowaną przez P1 (ta sama sesja i zakres). Funkcja @@ IDENTITY zwróci wartość wygenerowaną przez P2 (ta sama sesja, niezależnie od zakresu).

Dmitriy Dokshin
źródło