sql - transact - Il modo migliore per ottenere l'identità della riga inserita?




tsql select where (8)

Qual è il modo migliore per ottenere l' IDENTITY della riga inserita?

Conosco @@IDENTITY e IDENT_CURRENT e SCOPE_IDENTITY ma non capisco i pro ei contro associati a ciascuno.

Qualcuno può spiegare le differenze e quando dovrei usarle?


Credo che il metodo più sicuro e accurato per recuperare l'id inserito utilizzi la clausola di output.

per esempio (tratto dal seguente articolo di 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

Dopo la tua dichiarazione di inserimento è necessario aggiungere questo. E Assicurati del nome della tabella in cui i dati si stanno inserendo. Si otterrà la riga corrente no dove la riga è stata interessata solo ora dall'istruzione insert.

IDENT_CURRENT('tableName')

Inserisci

SELECT CAST(scope_identity() AS int);

alla fine della tua istruzione SQL insert, quindi

NewId = command.ExecuteScalar()

lo recupererà.


Non riesco a parlare con altre versioni di SQL Server, ma nel 2012, l'output diretto funziona correttamente. Non devi preoccuparti di un tavolo temporaneo.

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

A proposito, questa tecnica funziona anche quando si inseriscono più righe.

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

Produzione

ID
2
3
4

Sto dicendo la stessa cosa degli altri ragazzi, quindi tutti sono corretti, sto solo cercando di renderlo più chiaro.

@@IDENTITY restituisce l'ID dell'ultima cosa che è stata inserita dalla connessione del client al database.
La maggior parte delle volte funziona bene, ma a volte un trigger andrà e inserirà una nuova riga di cui non si è a conoscenza, e si otterrà l'ID da questa nuova riga, anziché quella che si desidera

SCOPE_IDENTITY() risolve questo problema. Restituisce l'id dell'ultima cosa che hai inserito nel codice SQL che hai inviato al database. Se i trigger vanno e creano righe aggiuntive, non causeranno il ritorno del valore sbagliato. urrà

IDENT_CURRENT restituisce l'ultimo ID che è stato inserito da chiunque. Se alcune altre app dovessero inserire un'altra riga in un momento non pianificato, otterrai l'ID di quella riga anziché la tua.

Se vuoi giocare sul sicuro, usa sempre SCOPE_IDENTITY() . Se ti attacchi con @@IDENTITY e qualcuno decide di aggiungere un trigger in seguito, tutto il tuo codice si interromperà.


MSDN

@@ IDENTITY, SCOPE_IDENTITY e IDENT_CURRENT sono funzioni simili in quanto restituiscono l'ultimo valore inserito nella colonna IDENTITY di una tabella.

@@ IDENTITY e SCOPE_IDENTITY restituiranno l'ultimo valore di identità generato in qualsiasi tabella nella sessione corrente. Tuttavia, SCOPE_IDENTITY restituisce il valore solo nell'ambito corrente; @@ IDENTITY non è limitato a un ambito specifico.

IDENT_CURRENT non è limitato dall'ambito e dalla sessione; è limitato a una tabella specificata. IDENT_CURRENT restituisce il valore dell'identità generato per una tabella specifica in qualsiasi sessione e qualsiasi ambito. Per ulteriori informazioni, vedere IDENT_CURRENT.

  • IDENT_CURRENT è una funzione che accetta una tabella come argomento.
  • MSDN può restituire risultati confusi quando si ha un trigger sul tavolo
  • SCOPE_IDENTITY è il tuo eroe per la maggior parte del tempo.

SEMPRE usa scope_identity (), non c'è MAI bisogno di nient'altro.


  • @@IDENTITY restituisce l'ultimo valore di identità generato per qualsiasi tabella nella sessione corrente, attraverso tutti gli ambiti. Devi stare attento qui , dal momento che è attraverso gli ambiti. Potresti ottenere un valore da un trigger, invece della tua attuale dichiarazione.

  • SCOPE_IDENTITY() restituisce l'ultimo valore di identità generato per qualsiasi tabella nella sessione corrente e l'ambito corrente. Generalmente quello che vuoi usare .

  • IDENT_CURRENT('tableName') restituisce l'ultimo valore di identità generato per una tabella specifica in qualsiasi sessione e qualsiasi ambito. Questo ti permette di specificare da quale tabella vuoi il valore, nel caso in cui i due sopra non siano esattamente ciò di cui hai bisogno ( molto raro ). Inoltre, come @ Guy Starbuck ha menzionato, "Puoi usare questo se vuoi ottenere il valore corrente di IDENTITY per una tabella in cui non hai inserito un record."

  • La clausola OUTPUT dell'istruzione INSERT ti consente di accedere a ogni riga che è stata inserita tramite tale istruzione. Poiché è correlato all'istruzione specifica, è più semplice rispetto alle altre funzioni di cui sopra. Tuttavia, è un po ' più prolisso (è necessario inserirlo in una tabella variabile / tabella temporanea e quindi eseguire una query) e fornisce risultati anche in uno scenario di errore in cui viene eseguito il rollback dell'istruzione. Detto questo, se la tua query utilizza un piano di esecuzione parallelo, questo è l' unico metodo garantito per ottenere l'identità (a meno di disattivare il parallelismo). Tuttavia, viene eseguito prima dei trigger e non può essere utilizzato per restituire valori generati dal trigger.





tsql