Wie fügt man mehrere Datensätze ein und erhält den Identity-Wert?

Ich füge mehrere Datensätze in eine Tabelle A aus einer anderen Tabelle B ein. Gibt es eine Möglichkeit, den Identitätswert von Tabelle A-Datensatz zu erhalten und Tabelle b-Datensatz zu aktualisieren, ohne einen Cursor auszuführen?

Create Table A
(id int identity,
Fname nvarchar(50),
Lname nvarchar(50))

Create Table B
(Fname nvarchar(50),
Lname nvarchar(50),
NewId int)

Insert into A(fname, lname)
SELECT fname, lname
FROM B

Ich benutze MS SQL Server 2005.

0
Andy Irvings Antwort ist die beste. Trigger sind schwerfällig und funktionieren nicht gut für beliebige Operationen auf Ihrer Zieltabelle, insbesondere wenn Ihr Ziel temporär oder nur ein Zwischenziel ist. Darrens Antwort ist falsch, wenn Sie eine Reihe von Zeilen einfügen, entspricht ihre Reihenfolge in der Zieltabelle nicht unbedingt der Reihenfolge Ihrer Gruppe. Dmitrys Weg ist schlecht, weil es eine Schleife um das Einfügen einer einzelnen Zeile zu einer Zeit erfordert, die langsam leistungsfähig ist, verwenden Sie immer Sätze, wenn Sie können. Corys Weg ist schlecht und er erklärt warum,
hinzugefügt der Autor clemahieu, Quelle
Ich weiß, dass dies eine alte Frage ist und SQL Server 2005 spezifiziert, aber da es das erste Ergebnis ist, sollte die MERGE-Anweisung, die 2008 und später verfügbar war, für diejenigen, die nach einer Lösung suchen, erwähnt werden. MERGE IN TargetTable VERWENDUNG (AUSWÄHLEN ....) AS Quelle EIN 1 = 2 WENN NICHT ABGESTIMMT DANN EINFÜGEN .... AUSGANG eingefügt.ID INTO TempTabelle (Eingefügte ID)
hinzugefügt der Autor oldegreyg, Quelle
Sie brauchen keine Zusammenführung für eine einfache Einfügung. Merge ist gut für ein Insert/Update, aber Overkill für ein einfaches Einfügen in. Andys Ausgabe-Antwort funktionierte für mich und half, eine Indexsperre wegzunehmen.
hinzugefügt der Autor CodeMonkeyForHire, Quelle

7 Antworten

Sie können das erreichen, indem Sie auf die Zeilennummer klicken. Dies ist möglich, da es sich um eine Identität handelt, die beim Hinzufügen von Elementen nur inkrementiert wird, und zwar in der Reihenfolge, in der Sie sie auswählen.

0
hinzugefügt
Falsch, Datensätze werden nicht garantiert in die Datenbank in der Reihenfolge gehen, in der Sie denken, dass sie gehen.
hinzugefügt der Autor HLGEM, Quelle

Soweit ich es verstehe, ist das Problem, das Sie haben, dass Sie INSERT in Tabelle A einfügen möchten, die über eine Identitätsspalte verfügt, und Sie möchten die Identität von Tabelle B erhalten, die das nicht tut.

Um dies zu tun, sollten Sie nur die Identität einfügen in Tabelle A einschalten. Dadurch können Sie Ihre IDs beim Einfügen definieren und solange sie nicht in Konflikt stehen, sollten Sie in Ordnung sein. Dann kannst du einfach tun:

Insert into A(identity, fname, lname) SELECT newid, fname, lname FROM B

Nicht sicher, welche DB Sie verwenden, aber fürSQL-serverwäre der Befehl zum Aktivieren der Identitätseinfügung:

set identity_insert A on
0
hinzugefügt
Er versucht nicht, Tabelle A zu aktualisieren, er versucht, Tabelle B zu aktualisieren. Tabelle B hat keine Identitätsspalte.
hinzugefügt der Autor njr101, Quelle

Wenn Sie Ihre Frage sorgfältig lesen, möchten Sie nur Tabelle B basierend auf den neuen Identitätswerten in Tabelle A aktualisieren.

Nachdem die Einfügung abgeschlossen ist, führen Sie einfach ein Update ...

UPDATE B
SET NewID = A.ID
FROM B INNER JOIN A
     ON (B.FName = A.Fname AND B.LName = A.LName)

Dies setzt voraus, dass die Kombination FName/LName verwendet werden kann, um die Datensätze zwischen den Tabellen mit Schlüsseln abzugleichen. Wenn dies nicht der Fall ist, müssen Sie möglicherweise zusätzliche Felder hinzufügen, um sicherzustellen, dass die Datensätze korrekt übereinstimmen.

Wenn Sie keinen alternativen Schlüssel haben, mit dem Sie die Datensätze abgleichen können, ergibt das überhaupt keinen Sinn, da die Datensätze in Tabelle B nicht voneinander unterschieden werden können.

0
hinzugefügt

MBelly ist richtig im Geld - Aber dann wird der Trigger immer versuchen, Tabelle B zu aktualisieren, auch wenn das nicht erforderlich ist (Weil Sie auch aus Tabelle C einfügen?).

Darren ist auch hier richtig, du kannst nicht mehrere Identitäten zurückbekommen, als Ergebnis gesetzt. Ihre Optionen verwenden einen Cursor und nehmen die Identität für jede Zeile, die Sie einfügen, oder den Darren-Ansatz zum Speichern der Identität vor und nach. Solange Sie das Inkrement der Identität kennen, sollte dies funktionieren, solange Sie sicherstellen, dass die Tabelle für alle drei Ereignisse gesperrt ist.

Wenn ich es wäre und es nicht zeitkritisch wäre, würde ich mit einem Cursor gehen.

0
hinzugefügt

Wenn Sie dieses Verhalten immer möchten, können Sie einen AFTER INSERT-Trigger für TableA verwenden, der Tabelle B aktualisiert.

0
hinzugefügt

Ich schlage vor, uniqueidentifier Typ anstelle von Identität zu verwenden. In diesem Fall können Sie IDs vor dem Einfügen generieren:

update B set NewID = NEWID()

insert into A(fname,lname,id) select fname,lname,NewID from B
0
hinzugefügt

Verwenden Sie die Ausgabeklausel von 2005:

DECLARE @output TABLE (id int)

Insert into A (fname, lname)
OUTPUT inserted.ID INTO @output
SELECT fname, lname FROM B

select * from @output

Jetzt hat Ihre Tabellenvariable die Identitätswerte aller Zeilen, die Sie einfügen.

0
hinzugefügt
@munissor, ich weiß, das ist ein alter Thread, aber schau dir dieser simple-talk Artikel zum Thema. Sehen Sie sich den Abschnitt "Hinzufügen einer OUTPUT-Klausel" an.
hinzugefügt der Autor Mr Moose, Quelle
Beachten Sie, dass dies kläglich versagt, wenn Tabelle A einen Auslöser hat, weil ein Fehler, den Microsoft nicht beheben kann. Eine weitere Problemumgehung finden Sie hier: stackoverflow.com/q/13198476/2557263
hinzugefügt der Autor Alejandro, Quelle
@munissor etwas spät, aber Sie können tun output insert.id, insert.whateverColumn in @output
hinzugefügt der Autor Dennis Rongo, Quelle
Aber wie aktualisieren Sie dann Tabelle B? Ich meine, wie verbindet man jeden Datensatz von @output mit einem Datensatz in B? Wenn Sie fname, lname als Schlüssel verwenden, ist es einfacher, njrs Lösung zu verwenden.
hinzugefügt der Autor munissor, Quelle
@DennisRongo nur wenn insert.whateverColumn eine andere eindeutige Kennung ist ...
hinzugefügt der Autor Mark, Quelle