SQL Server - Retourwaarde na INSERT

Ik probeer de sleutelwaarde terug te krijgen na een INSERT-verklaring. Voorbeeld: Ik heb een tabel met de kenmerken naam en id. id is een gegenereerde waarde.

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

Nu wil ik de ID terug in dezelfde stap krijgen. Hoe is dit gebeurd?

We gebruiken Microsoft SQL Server 2008.

211
toegevoegd de auteur Vladimir Vagaytsev, de bron
Ik vond hier een bruikbaar antwoord: [preparedstatement-with-statement-return-generated-keys] [1] [1]: stackoverflow.com/questions/4224228/…
toegevoegd de auteur Lars Ladegaard, de bron

10 antwoord

Geen behoefte aan een aparte SELECT ...

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

Dit werkt ook voor niet-IDENTITEIT kolommen (zoals GUID's)

343
toegevoegd
Hé, heb je het op SO/SE gegeven? Je laatste bericht was op 13 december. Aangezien dat alleen maar opmerkingen maakt.
toegevoegd de auteur abatishchev, de bron
@ JonnyLeeds: u kunt dit niet doen voor een variabele (tenzij een tabelvariabele). De OUTPUT gaat naar de client of een tafel
toegevoegd de auteur gbn, de bron
@hajikelist: dit is nogal een edge-case, SET NCOOUNT ON in de trigger helpt meestal. Zie stackoverflow.com/questions/1483732/set-nocount-on-usage
toegevoegd de auteur gbn, de bron
Gebruik nooit @@ IDENTITY. SCOPE_IDENTITY, ja, maar nooit @@ IDENTITY. Het is onbetrouwbaar
toegevoegd de auteur gbn, de bron
zou je een beetje kunnen uitwerken? Waar gaat de uitvoer in dit voorbeeld naartoe? De documentatie toont alleen voorbeelden voor tabellen (met uitvoer ... in ). Idealiter zou ik het gewoon in een variabele willen doorgeven
toegevoegd de auteur Jonny Leeds, de bron
U kunt ook @@ IDENTITY en anderen gebruiken. En de clausuleorde is belangrijk! (ontdek de harde manier ...)
toegevoegd de auteur Z. Khullah, de bron
@gbn Ik ben het hier niet mee eens - triggers zijn extreem vaak. Ik weet niet zeker of het instellen van NOCOUNT dit corrigeert, lees dat msdn bericht voor een diepere uitleg.
toegevoegd de auteur hajikelist, de bron
Helaas kunt u hier niet op vertrouwen, omdat het toevoegen van een trigger aan de tafel uw uitspraken zal breken! re: blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/…
toegevoegd de auteur hajikelist, de bron

Gebruik SCOPE_IDENTITY() om de nieuwe ID-waarde te krijgen

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

SELECT SCOPE_IDENTITY()

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

126
toegevoegd
@ liho1eye - Het OP verwees naar de naam van de identiteitskolom als id , dus ja.
toegevoegd de auteur Curt, de bron
ervan uitgaande dat id identiteit is
toegevoegd de auteur Ilia G, de bron
Op een groter systeem, wat als veel sql's tegelijkertijd worden uitgevoerd? Zal het de laatst ingevoegde ID aan elk verzoek retourneren?
toegevoegd de auteur Shiv, de bron
@Shiv "SCOPE_IDENTITY retourneert waarden die alleen in het huidige bereik zijn ingevoegd"
toegevoegd de auteur goodies4uall, de bron
INSERT INTO files (title) VALUES ('whatever'); 
SELECT * FROM files WHERE id = SCOPE_IDENTITY();

Is de veiligste gok aangezien er een bekend probleem is met OUTPUT Clausuleconflicten op tabellen met triggers. Maakt dit vrij onbetrouwbaar, zelfs als uw tabel momenteel geen triggers heeft - iemand die er één toevoegt, zal uw toepassing verbreken. Time Bomb soort gedrag.

Zie msdn-artikel voor een diepere uitleg:

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

30
toegevoegd
@hajikelist We hebben allemaal een erfenis, maar het risico dat triggers UITGANG veroorzaken, is laag, alles wat nodig is, zet je op nul. Als iemand een trigger toevoegt, moeten deze weten hoe deze moet worden gecodeerd (wat inhoudt dat je voornamelijk controle hebt), of je moet je ontwikkelaars trainen. Op een gegeven moment moet je migreren als die versie van SQL niet meer bestaat ondersteund enz. dus triggers zullen geen resultat veroorzaken. Wat dan ook, het is niet het beste antwoord, want als je INSTEAD OF triggers hebt, werkt de SCOPE_IDENTITY mogelijk niet (SQL-serververliest scope-identiteit% 23 "> stackoverflow.com/questions/908257/… )
toegevoegd de auteur gbn, de bron
Alleen als u SET NOCOUNT ON niet toevoegt in triggers. Zie ook docs.microsoft.com/en-us/sql/database-engine/configure-windo‌ ws/& hellip;
toegevoegd de auteur gbn, de bron
dit is geen optie voor onze oudere omgevingen @gbn
toegevoegd de auteur hajikelist, de bron
@gbn - Ik wil graag domme dingen zoals dit vermijden. Ik ga niet al mijn ontwikkelaars vertellen: "Vergeet niet om de app-mijn app-instructie niet toe te voegen" in elke trigger. " - je kan het houden. Het "in plaats daarvan" scenario is veel meer een edge-case imo.
toegevoegd de auteur hajikelist, de bron

Entity Framework voert iets vergelijkbaars uit als het antwoord van 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

De uitvoerresultaten worden opgeslagen in een tijdelijke tabelvariabele en vervolgens terug geselecteerd naar de client. Wees op de hoogte van de gotcha:

invoegingen kunnen meer dan één rij genereren, dus de variabele kan meer dan één rij bevatten, zodat u meer dan één ID

kunt retourneren

Ik heb geen idee waarom EF innerlijk tot de vluchtige tafel zou toetreden tot de echte tafel (onder welke omstandigheden zouden de twee niet overeenkomen).

Maar dat is wat EF doet.

Alleen SQL Server 2008 of nieuwer. Als het 2005 is, heb je pech.

12
toegevoegd

@@ IDENTITY Is een systeemfunctie die de laatst ingevoerde identiteitswaarde retourneert.

7
toegevoegd
Moet nooit adviseren @@ IDENTITY te gebruiken - het is niet correct (te breed), veel minder thread-safe - zie @ Curt's antwoord over SCOPE_IDENTITY ().
toegevoegd de auteur zanlok, de bron

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
toegevoegd
ja, gebruik het nooit. het werkt niet altijd goed: X
toegevoegd de auteur H.Ghassami, de bron
Gebruik nooit @@ IDENTITY: het is niet veilig voor het bereik: triggers, enz. Hebben hier invloed op.
toegevoegd de auteur gbn, de bron

U kunt de functie scope_identity gebruiken om de ID van de rij te selecteren die u zojuist in een variabele hebt ingevoegd. Selecteer vervolgens de gewenste kolommen in de tabel waarin de id = de identiteit die u van scope_identity heeft gekregen

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

3
toegevoegd

* 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.

Nadat een rij is toegevoegd, zijn de rijvelden niet beschikbaar, TENZIJ de Provider is opgegeven als de eerste parameter in de verbindingsreeks. Wanneer de provider zich ergens in de verbindingsreeks bevindt, behalve als de eerste parameter, zijn de nieuw ingevoerde rijvelden niet beschikbaar. Toen we de Provider naar de eerste parameter verplaatsten, verschenen de rijvelden op magische wijze.

2
toegevoegd
U moet uw antwoord bewerken en verbeteren. Het is momenteel lawaaierig en komt niet over als een fatsoenlijk antwoord of zelfs een poging
toegevoegd de auteur James, de bron
Veel gebruikers zijn waarschijnlijk naar deze pagina gekomen omdat ze geen geldige velden hadden om de zojuist toegevoegde rij te identificeren. Dit gedrag dat we vonden (dat simpelweg het veranderen van de volgorde van de parameters in de verbindingsstring het mogelijk maakt om direct toegang te krijgen tot de nieuw toegevoegde rij) is zo bizar dat ik dacht dat het het vermelden waard was in caps, vooral omdat het zeer waarschijnlijk de reden zal bevestigen dat mensen de nieuwe willen rij-ID en andere velden van die rij. Door simpelweg de provider als de eerste parameter te plaatsen, verdwijnt het probleem.
toegevoegd de auteur David Guidos, de bron
Wat bedoel je precies met "luidruchtig"? U moet uw klacht toelichten. Het gaat zo eenvoudig als het kan zijn. Als u de volgorde van de parameters in uw verbindingsreeks wijzigt, kan dit invloed hebben op de vraag of rijgegevens beschikbaar zijn na een invoeging.
toegevoegd de auteur David Guidos, de bron
Kun je ons vertellen hoe deze opmerking antwoordt/relevant is voor de vraag die werd gesteld? Ik vind niet dat het caps/bold verdient. Als uw antwoord nuttig wordt geacht, zullen gebruikers het stemmen.
toegevoegd de auteur n__o, de bron

U kunt een select-statement toevoegen aan uw insert-statement. Integer myInt = Voeg in tabel1 (FName) waarden ('Fred'); Selecteer Scope_Identity (); Dit zal een waarde van de identiteit teruggeven wanneer de uitgevoerde scaler wordt uitgevoerd.

0
toegevoegd

Dit is hoe ik OUTPUT INSERTED gebruik, wanneer ik invoegen in een tabel die ID gebruikt als identiteitskolom 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)
0
toegevoegd