SQL Server - valoarea returnată după INSERT

Încerc să obțin o valoare cheie după o declarație INSERT. Exemplu: Am un tabel cu numele și id-ul atributelor. id este o valoare generată.

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

Acum vreau să-l iau pe id înapoi în același pas. Cum se face acest lucru?

Folosim Microsoft SQL Server 2008.

211
adăugat autor Vladimir Vagaytsev, sursa
Am găsit un răspuns util aici: [executed-with-statement-return-generated-keys] [1]: stackoverflow.com/questions/4224228/…
adăugat autor Lars Ladegaard, sursa

10 răspunsuri

Nu este nevoie de un SELECT separat ...

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

Aceasta funcționează și pentru coloanele non-IDENTITY (cum ar fi GUID-urile)

343
adăugat
Hei, ai dat pe SO/SE? Ultima ta înregistrare a fost pe data de 14 decembrie. Din moment ce doar comentariile.
adăugat autor abatishchev, sursa
@JonnyLeeds: nu o puteți face unei variabile (cu excepția unei variabile de masă). OUTPUT-ul merge la client sau la un tabel
adăugat autor gbn, sursa
@hajikelist: acesta este un caz de margine destul de mare, SET NCOOUNT ON în declanșator de obicei ajută. Consultați stackoverflow.com/questions/1483732/set-nocount-on-usage
adăugat autor gbn, sursa
Nu folosiți niciodată @@ IDENTITY. SCOPE_IDENTITY, da, dar niciodată @@ IDENTITY. Este nesigur
adăugat autor gbn, sursa
ai putea elabora un pic? Unde se face ieșirea în acest exemplu? Documentația arată numai exemple pentru tabele (utilizând ieșirea ... în ). În mod ideal, aș vrea să fiu capabil să o transmit într-o variabilă
adăugat autor Jonny Leeds, sursa
Puteți utiliza @@ IDENTITY și altele, de asemenea. Și ordinea clauzelor contează! (a descoperit calea grea ..)
adăugat autor Z. Khullah, sursa
@gbn Nu sunt de acord - declanșatoarele sunt extrem de comune. Nu sunt sigur că setarea NOCOUNT stabilește că, vă rugăm să citiți prin acel mesaj MSDN pentru o explicație mai profundă.
adăugat autor hajikelist, sursa
Din păcate, nu te poți baza pe asta, deoarece adăugarea unui declanșator la masă îți va sparge afirmațiile! re:
adăugat autor hajikelist, sursa

Utilizați SCOPE_IDENTITY() pentru a obține noua valoare ID

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

SELECT SCOPE_IDENTITY()

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

126
adăugat
@ liho1eye - OP a făcut referire la numele coloanei de identitate ca id , deci da.
adăugat autor Curt, sursa
presupunând că id este identitate
adăugat autor Ilia G, sursa
Pe un sistem mai mare, ce se întâmplă dacă mai multe site-uri rulează în același timp? Va returna ultimul cod introdus la fiecare cerere?
adăugat autor Shiv, sursa
@Shiv "SCOPE_IDENTITY returnează valori introduse numai în domeniul de aplicare actual"
adăugat autor goodies4uall, sursa
INSERT INTO files (title) VALUES ('whatever'); 
SELECT * FROM files WHERE id = SCOPE_IDENTITY();

Este cel mai sigur pariu, deoarece există o problemă cunoscută cu conflictul clauzei OUTPUT pe tabelele cu declanșatoare. Face acest lucru destul de nesigur ca chiar dacă masa dvs. nu are în prezent niciun declanșator - cineva care adaugă unul pe linie va rupe aplicația. Time Bomb, un fel de comportament.

Vedeți articolul msdn pentru o explicație mai profundă:

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

30
adăugat
@hajikelist Suntem cu toții moșteniți, dar riscul de declanșare a deranjamentului OUTPUT este scăzut, tot ce este necesar este setat pe noapte. Dacă cineva este adăugarea unui declanșator atunci ei ar trebui să știe cum să-l cod (implică aveți de control principal), sau aveți nevoie pentru a instrui dezvoltatorii .. La un moment dat, vei fi obligat să migreze în momentul în care versiunea de SQL nu mai suportate etc. astfel încât declanșatoarele nu vor cauza un rezultat. Oricare ar fi, nu este cel mai bun răspuns pentru că dacă aveți declanșează în locul SCOPE_IDENTITY s-ar putea să nu funcționeze ( stackoverflow.com/questions/908257/… )
adăugat autor gbn, sursa
Doar dacă nu adăugați SET NOCOUNT ON în declanșatoare. De asemenea, vedeți
adăugat autor gbn, sursa
aceasta nu este o opțiune pentru mediile noastre vechi @ gbn
adăugat autor hajikelist, sursa
@gbn - Îmi place să evit lucrurile stupide ca asta. Nu voi spune tuturor dezvoltatorilor mei: "Nu uitați să adăugați rubrica" ​​Nu întrerupeți declarația aplicației mele "în fiecare declanșare. - o poti pastra. Scenariul "în loc" este cu mult mai mult decât un imo.
adăugat autor hajikelist, sursa

Entity Framework efectuează ceva similar cu răspunsul 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

Rezultatele rezultatelor sunt stocate într-o variabilă tabelă temporară și apoi selectate înapoi la client. Trebuie să fie conștienți de faptul că am primit:

inserțiile pot genera mai mult de un rând, deci variabila poate conține mai mult de un rând, astfel încât să puteți fi returnate mai mult de un ID

Nu am idee de ce EF ar intra în interiorul mesei efemere înapoi la masa reală (în ce circumstanțe nu s-ar potrivi cele două).

Dar asta face EF.

SQL Server 2008 sau mai nou. Dacă e în 2005, atunci nu ai noroc.

12
adăugat

@@ IDENTITY Este o funcție de sistem care returnează ultima valoare de identitate introdusă.

7
adăugat
Trebuie să vă sfătuim să nu utilizați niciodată @@ IDENTITY - nu este exactă (prea largă) mult mai puțin sigură pe fir - vă rugăm să consultați răspunsul lui Curt despre SCOPE_IDENTITY ().
adăugat autor zanlok, sursa

After doing an insert into a table with an identity column, you can reference @@IDENTITY to get the value: http://msdn.microsoft.com/en-us/library/aa933167%28v=sql.80%29.aspx

5
adăugat
da, nu-l folosiți niciodată. nu funcționează bine: X
adăugat autor H.Ghassami, sursa
Nu utilizați niciodată @@ IDENTITY: nu este un domeniu sigur: declanșează etc. și îl afectează.
adăugat autor gbn, sursa

Puteți utiliza identitatea scope_identity pentru a selecta ID-ul rândului pe care tocmai l-ați inserat într-o variabilă, apoi selectați oricare dintre coloanele dorite din tabelul în care id = identitatea pe care ați obținut-o din domeniul de aplicare

See here for the MSDN info http://msdn.microsoft.com/en-us/library/ms190315.aspx

3
adăugat

* Parameter order in the connection string is sometimes important. * The Provider parameter's location can break the recordset cursor after adding a row. We saw this behavior with the SQLOLEDB provider.

După adăugarea unui rând, câmpurile din rând nu sunt disponibile, DACĂ Furnizorul este specificat ca fiind primul parametru din șirul de conectare. Când furnizorul este oriunde în șirul de conexiune, cu excepția primului parametru, câmpurile de rând introduse recent nu sunt disponibile. Când am mutat Providerul la primul parametru, câmpurile de rând au apărut în mod magic.

2
adăugat
Trebuie să editați și să vă îmbunătățiți răspunsul. În prezent, este zgomotos și nu se întâlnește ca un răspuns decent sau chiar o încercare
adăugat autor James, sursa
O mulțime de utilizatori au venit probabil la această pagină, deoarece nu aveau câmpuri valide pentru a identifica rândul adăugat. Acest comportament pe care am descoperit-o (schimbarea pur și simplu a ordinii parametrilor din șirul de conectare permite accesarea imediat a noului rând adăugat) este atât de bizar, încât am crezut că este meritat să menționez în capace, mai ales că foarte probabil va rezolva motivul pentru care oamenii doresc noul ID-ul rândului și alte câmpuri ale acelui rând. Prin simpla punere a furnizorului ca prim parametru, problema dispare.
adăugat autor David Guidos, sursa
Ce anume înseamnă "zgomotos"? Trebuie să-ți explici plângerea. Este cam la fel de simplu cum poate fi. Dacă schimbați ordinea parametrilor din șirul de conexiune, acesta poate afecta dacă datele rând sunt disponibile după inserare.
adăugat autor David Guidos, sursa
Ne puteți spune cum răspunde acest comentariu/este relevant pentru întrebarea care a fost adresată? Nu simt că merită capace/îndrăzneț. Dacă răspunsul dvs. este considerat util, utilizatorii îl vor vota.
adăugat autor n__o, sursa

Puteți adăuga o instrucțiune selectată în instrucțiunea de inserare. Integritate myInt = Introduceți valorile tabelului1 (FName) ("Fred"); Selectați Scope_Identity (); Aceasta va întoarce o valoare a identității atunci când scalatorul executat.

0
adăugat

Acesta este modul în care folosesc OUTPUT INSERTED, atunci când inserați într-o tabelă care utilizează ID-ul ca coloană de identitate în 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)
0
adăugat