Cum să inserați mai multe înregistrări și să obțineți valoarea de identitate?

Am inserat mai multe înregistrări într-un tabel A dintr-un alt tabel B. Există o modalitate de a obține valoarea de identitate a tabelului A de înregistrare și de actualizare a tabelului b înregistrate fără a face un cursor?

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

Folosesc MS SQL Server 2005.

0
Răspunsul lui Andy Irving este cel mai bun. Declanșatoarele sunt stângaci și nu funcționează bine pentru operații arbitrare pe masa dvs. țintă, mai ales dacă obiectivul dvs. este temporar sau doar un intermediar. Răspunsul lui Darren este greșit, dacă introduceți un set de rânduri, ordinea lor în tabela țintă nu este neapărat aceeași cu ordinea setului. Modul lui Dmitry este rău pentru că necesită o buclă în jurul introducerii unui singur rând la un moment dat, care este performant lent în mod înțelept, folosiți întotdeauna seturi când puteți. Modul lui Cory este rău și el a explicat de ce, "a
adăugat autor clemahieu, sursa
Îmi dau seama că aceasta este o întrebare veche și se specifică SQL Server 2005, dar deoarece este primul rezultat pentru a afișa declarația MERGE disponibilă în 2008 și ulterior trebuie menționată pentru cei care caută o soluție. MERGE INTO TargetTable UTILIZAREA (SELECT ....) AS Sursa ON 1 = 2 CÂND NU ESTE MATCHED THEN INSERT .... OUTPUT introdus.ID INTO TempTable (ID inserat)
adăugat autor oldegreyg, sursa
Nu aveți nevoie de o îmbinare pentru o inserție simplă. Merge este bun pentru o inserare/actualizare, dar overkill pentru o inserare simplă în. Răspunsul de ieșire al lui Andy a lucrat pentru mine și a ajutat la eliminarea blocării indexului.
adăugat autor CodeMonkeyForHire, sursa

7 răspunsuri

Puteți obține accesul prin număr rând . Acest lucru este posibil deoarece din moment ce este o identitate, va crește doar pe măsură ce adăugați elemente, ceea ce va fi în ordinea în care le selectați.

0
adăugat
Înregistrările greșite nu sunt garantate pentru a intra în baza de date în ordinea în care credeți că intră.
adăugat autor HLGEM, sursa

Din câte am înțeles, problema pe care o aveți este că doriți să INSERȚI în tabelul A, care are o coloană de identitate și doriți să păstrați identitatea din tabelul B care nu o face.

Pentru a face acest lucru ar trebui să activați inserarea identității pe tabelul A. Acest lucru vă va permite să definiți ID-ul dvs. pe inserați și atâta timp cât acestea nu intră în conflict, trebuie să fiți bine. Apoi puteți să faceți:

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

Nu sunteți sigur ce DB utilizați, dar pentru serverul SQL comanda pentru a activa inserarea identității ar fi:

set identity_insert A on
0
adăugat
Nu încearcă să actualizeze tabelul A, încearcă să actualizeze tabelul B. Tabelul B nu conține o coloană de identitate.
adăugat autor njr101, sursa

Citind cu atenție întrebarea dvs., doriți doar să actualizați tabelul B, pe baza noilor valori identitare în tabelul A.

După ce inserarea sa terminat, executați doar o actualizare ...

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

Aceasta presupune că combinația FName/LName poate fi utilizată pentru a potrivi cheile cu înregistrările între tabele. Dacă nu este cazul, este posibil să fie necesar să adăugați câmpuri suplimentare pentru a vă asigura că înregistrările se potrivesc corect.

Dacă nu aveți o cheie alternativă care vă permite să potriviți înregistrările, atunci nu are nici un sens, deoarece înregistrările din tabelul B nu pot fi distinse una de cealaltă.

0
adăugat

MBelly are dreptate pe bani - Dar apoi declanșatorul va încerca întotdeauna să actualizeze tabelul B chiar dacă nu este necesar (pentru că introduceți și din tabelul C?).

Darren este, de asemenea, corect aici, nu puteți obține mai multe identități înapoi ca set de rezultate. Opțiunile dvs. folosesc un cursor și luați identitatea pentru fiecare rând pe care îl inserați sau folosiți abordarea lui Darren de a stoca identitatea înainte și după. Atâta timp cât cunoașteți creșterea identității, aceasta ar trebui să funcționeze, atât timp cât vă asigurați că masa este blocată pentru toate cele trei evenimente.

Dacă aș fi fost eu și nu era critic de timp, m-aș duce cu un cursor.

0
adăugat

Dacă doriți întotdeauna acest comportament, puteți pune un trigger AFTER INSERT pe TableA care va actualiza tabelul B.

0
adăugat

Vă sugerăm să utilizați un tip de identificator unic în loc de identitate. În acest caz, puteți genera ID-uri înainte de inserare:

update B set NewID = NEWID()

insert into A(fname,lname,id) select fname,lname,NewID from B
0
adăugat

Utilizați clauza ouput din 2005:

DECLARE @output TABLE (id int)

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

select * from @output

acum variabila dvs. de tabel are valorile identitare ale tuturor rândurilor introduse.

0
adăugat
@munissor, știu că acesta este un fir vechi, dar verificați acest articol simplu-talk pe subiect. Consultați secțiunea "Adăugarea unei clauze OUTPUT".
adăugat autor Mr Moose, sursa
Rețineți că acest lucru nu reușește în mod neplăcut când tabelul A are un declanșator, deoarece un bug pe care Microsoft refuză să îl repare. O altă soluție este aici: stackoverflow.com/q/13198476/2557263
adăugat autor Alejandro, sursa
Dar cum actualizați tabelul B? Vreau să spun, cum asociați fiecare înregistrare a lui @output cu o înregistrare în B? Dacă utilizați fname, lname ca cheie, atunci este mai simplu să utilizați soluția njr.
adăugat autor munissor, sursa
@DennisRongo numai dacă inserted.whateverColumn este un alt identificator unic ...
adăugat autor Mark, sursa