Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

IDENT_CURRENT vs @@IDENTITY vs SCOPE_IDENTITY in SQL Server:qual è la differenza?

In SQL Server, se è necessario restituire il valore creato in una colonna Identity, sono disponibili diverse opzioni. Ognuna di queste opzioni, sebbene simile, fa una cosa leggermente diversa.

In particolare, puoi utilizzare le seguenti funzioni:

  • IDENT_CURRENT() restituisce l'ultimo valore di identità inserito per una determinata tabella.
  • SCOPE_IDENTITY() restituisce l'ultimo valore di identità inserito in una colonna di identità in qualsiasi tabella nella sessione corrente e nell'ambito corrente.
  • @@IDENTITY restituisce l'ultimo valore di identità inserito in qualsiasi tabella nella sessione corrente, indipendentemente dall'ambito.

Esempio

Ecco un esempio che dimostra la differenza tra queste tre funzioni.

Innanzitutto, crea due tabelle. Nota i diversi valori di seed e di incremento utilizzati per la colonna identity in ogni tabella:

CREATE TABLE t1(id int IDENTITY(1,1));  
CREATE TABLE t2(id int IDENTITY(150,10));

Ora crea un trigger che inserisca una riga nella seconda tabella ogni volta che una riga viene inserita nella prima tabella:

CREATE TRIGGER t1_insert_trigger ON t1 FOR INSERT
AS
BEGIN
  INSERT t2 DEFAULT VALUES
END;

I trigger si attivano in un ambito diverso, quindi è perfetto per il mio esempio qui.

Inserisci i dati nella prima tabella, quindi seleziona i risultati da entrambe le tabelle:

INSERT t1 DEFAULT VALUES;
SELECT id AS t1 FROM t1;
SELECT id AS t2 FROM t2;

Risultato:

+------+
| t1   |
|------|
| 1    |
+------+
(1 row affected)
+------+
| t2   |
|------|
| 150  |
+------+
(1 row affected)

Quindi, tanto per essere chiari, questi dati sono stati inseriti da due ambiti diversi. L'inserto in t1 è stato fatto nell'ambito di applicazione attuale. L'inserto in t2 è stato eseguito dal trigger, che è stato eseguito in un ambito diverso.

Ora selezioniamo tra le funzioni citate in precedenza:

SELECT 
  @@IDENTITY AS [@@IDENTITY],
  SCOPE_IDENTITY() AS [SCOPE_IDENTITY()],
  IDENT_CURRENT('t1') AS [IDENT_CURRENT('t1')],
  IDENT_CURRENT('t2') AS [IDENT_CURRENT('t2')];

Risultato:

+--------------+--------------------+-----------------------+-----------------------+
| @@IDENTITY   | SCOPE_IDENTITY()   | IDENT_CURRENT('t1')   | IDENT_CURRENT('t2')   |
|--------------+--------------------+-----------------------+-----------------------|
| 150          | 1                  | 1                     | 150                   |
+--------------+--------------------+-----------------------+-----------------------+

Il risultato restituito da @@IDENTITY non è limitato all'ambito e pertanto restituisce l'ultimo valore di identità inserito, indipendentemente dall'ambito.

SCOPE_IDENTITY() restituisce il valore di identità dalla prima tabella, perché quello era l'ultimo valore di identità inserito nell'ambito corrente (il trigger è al di fuori dell'ambito corrente).

Il IDENT_CURRENT() La funzione restituisce semplicemente l'ultimo valore di identità inserito nella tabella specificata, indipendentemente dall'ambito o dalla sessione.

Apri una nuova sessione

Ora, ecco cosa succede se apro una nuova sessione ed eseguo di nuovo l'istruzione precedente:

USE Test;
SELECT 
  @@IDENTITY AS [@@IDENTITY],
  SCOPE_IDENTITY() AS [SCOPE_IDENTITY()],
  IDENT_CURRENT('t1') AS [IDENT_CURRENT('t1')],
  IDENT_CURRENT('t2') AS [IDENT_CURRENT('t2')];

Risultato:

+--------------+--------------------+-----------------------+-----------------------+
| @@IDENTITY   | SCOPE_IDENTITY()   | IDENT_CURRENT('t1')   | IDENT_CURRENT('t2')   |
|--------------+--------------------+-----------------------+-----------------------|
| NULL         | NULL               | 1                     | 150                   |
+--------------+--------------------+-----------------------+-----------------------+

Entrambi @@IDENTITY e SCOPE_IDENTITY() sono NULL perché restituiscono solo i risultati della sessione corrente. Non ho eseguito alcun inserimento di colonne di identità in questa nuova sessione, quindi ottengo NULL.

IDENT_CURRENT() d'altra parte, restituisce lo stesso risultato dell'esempio precedente, sempre perché i suoi risultati sono basati sulla tabella specificata, indipendentemente dalla sessione o dall'ambito.