2011-10-27 20 views
192

Sto cercando di ottenere un valore-chiave dopo un'istruzione INSERT. Esempio: Ho una tabella con gli attributi nome e id. id è un valore generato.SQL Server - Valore restituito dopo INSERTO

INSERT INTO table (name) VALUES('bob'); 

Ora voglio riportare l'ID nello stesso passo. Come è fatto?

Stiamo utilizzando Microsoft SQL Server 2008.

+0

Ho trovato un utile risposta qui: [PreparedStatement-con-chiavi generate dichiarazione-ritorno-] [1] [1]: http://stackoverflow.com/questions/4224228/preparedstatement- with-statement-return-generated-keys –

+1

Possibile duplicato di [Il modo migliore per ottenere l'identità della riga inserita?] (http://stackoverflow.com/questions/42648/best-way-to-get-identity-of-inserted -row) –

risposta

315

No necessità di un SELECT separata ...

INSERT INTO table (name) 
OUTPUT Inserted.ID 
VALUES('bob'); 

Questo funziona per le colonne non di identità (come ad esempio GUID) troppo

+12

potresti elaborare un po '? Dove va l'uscita in questo esempio? [La documentazione] (http://technet.microsoft.com/en-us/library/ms177564.aspx) mostra solo esempi di tabelle (utilizzando l'output ... in). Idealmente mi piacerebbe essere in grado di passarlo in una variabile –

+2

@JonnyLeeds: non puoi farlo su una variabile (a meno che non sia una variabile di tabella). L'OUTPUT va al cliente oa un tavolo – gbn

+2

Sfortunatamente, non puoi fare affidamento su questo poiché aggiungere un trigger al tavolo infrange le tue affermazioni! re: http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx – hajikelist

116

Usa SCOPE_IDENTITY() per ottenere il nuovo valore ID

INSERT INTO table (name) VALUES('bob'); 

SELECT SCOPE_IDENTITY() 

http://msdn.microsoft.com/en-us/library/ms190315.aspx

+4

assumendo 'id' è identità –

+8

@ liho1eye - L'OP si riferisce al nome della colonna Identity come' id', quindi sì. – Curt

+1

Su un sistema più grande, cosa succede se molti sql vengono eseguiti contemporaneamente? Restituirà l'ultimo ID inserito per ogni richiesta? – Shiv

25
INSERT INTO files (title) VALUES ('whatever'); 
SELECT * FROM files WHERE id = SCOPE_IDENTITY(); 

È la scommessa più sicura poiché esiste un problema noto con il conflitto delle clausole OUTPUT sulle tabelle con trigger. Rende questo abbastanza inaffidabile come anche se la tua tabella non ha attualmente alcun trigger - qualcuno che ne aggiunge uno in basso interromperà la tua applicazione. Tipo di comportamento Time Bomb.

articolo Vedere MSDN per spiegazione più profonda:

http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx

+0

Questa è di gran lunga la migliore risposta. –

-2

* ordine dei parametri nella stringa di connessione è a volte importante. * La posizione del parametro Provider può interrompere il cursore del recordset dopo aver aggiunto una riga. Abbiamo visto questo comportamento con il provider SQLOLEDB.

Dopo aver aggiunto una riga, i campi di riga non sono disponibili, A MENO che il Provider sia specificato come primo parametro nella stringa di connessione. Quando il provider si trova in un punto qualsiasi della stringa di connessione, ad eccezione del primo parametro, i campi di riga appena inseriti non sono disponibili. Quando abbiamo spostato il Provider sul primo parametro, i campi riga sono stati visualizzati magicamente.

+1

Potresti dirci in che modo questo commento risponde/è pertinente alla domanda che è stata fatta? Non credo che meriti i cappucci/grassetto. Se la tua risposta è ritenuta utile, gli utenti la voteranno. –

+0

Probabilmente molti utenti sono venuti in questa pagina perché non avevano campi validi per identificare la riga appena aggiunta. Questo comportamento che abbiamo trovato (che semplicemente cambiando l'ordine dei parametri nella stringa di connessione consente di accedere immediatamente alla riga appena aggiunta) è così bizzarro che pensavo meritasse di menzionarlo in caps, soprattutto perché molto probabilmente aggiusterà il motivo per cui le persone vogliono il nuovo riga ID e altri campi di quella riga.Semplicemente inserendo il provider come primo parametro, il problema scompare. –

+0

È necessario modificare e migliorare la risposta. Attualmente è rumoroso e non si presenta come una risposta decente o addirittura un tentativo – James

0

Questo è come io uso OUTPUT inserito, quando si inserisce in una tabella che utilizza ID come colonna di identità in SQL Server:

'myConn is the ADO connection, RS a recordset and ID an integer 
Set RS=myConn.Execute("INSERT INTO M2_VOTELIST(PRODUCER_ID,TITLE,TIMEU) OUTPUT INSERTED.ID VALUES ('Gator','Test',GETDATE())") 
ID=RS(0) 
11

Entity Framework esegue qualcosa di simile alla risposta di gbn:

DECLARE @generated_keys table([Id] uniqueidentifier) 

INSERT INTO Customers(FirstName) 
OUTPUT inserted.CustomerID INTO @generated_keys 
VALUES('bob'); 

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

I risultati di output sono memorizzati in una variabile di tabella temporanea e quindi selezionati nuovamente nel client.Devono essere consapevoli del Gotcha:

inserti in grado di generare più di una riga, quindi la variabile può contenere più di una riga, in modo da poter essere restituito più di un ID

non ho idea del motivo per cui EF si unirebbe interiormente al tavolo effimero per tornare al tavolo reale (in quali circostanze i due non corrisponderebbero).

Ma questo è ciò che EF fa.

Solo SQL Server 2008 o versione successiva. Se è il 2005, allora sei sfortunato.

8

@@ IDENTITY È una funzione di sistema che restituisce il valore dell'identità inserito per ultimo.

0

È possibile aggiungere un'istruzione select all'istruzione di inserimento. Integer myInt = Inserisci in valori table1 (FName) ('Fred'); Seleziona Scope_Identity(); Questo restituirà un valore dell'identità quando viene eseguito il ridimensionamento.