Bagaimana cara menggunakan klausa OUTPUT pernyataan INSERT untuk mendapatkan nilai identitas?

240

Jika saya memiliki pernyataan masukkan seperti:

INSERT INTO MyTable
(  
  Name,
  Address,
  PhoneNo
)
VALUES
(
  'Yatrix',
   '1234 Address Stuff',
   '1112223333'
)

Bagaimana cara saya menetapkan @var INTnilai identitas baris baru (dipanggil Id) menggunakan klausa OUTPUT? Saya telah melihat contoh menempatkan INSERTED.Name ke dalam variabel tabel, misalnya, tapi saya tidak bisa memasukkannya ke dalam variabel non-tabel.

Saya sudah mencoba OUPUT INSERTED.Id AS @var, SET @var = INSERTED.Idtapi tidak berhasil.

Yatrix
sumber
3
Saya sudah tahu tentang @@ SCOPE_IDENTITY, saya secara khusus ingin tahu bagaimana melakukannya dengan OUPUT. Terima kasih.
Yatrix
6
Anda harus memasukkannya ke dalam variabel tabel lalu pilih dari itu. Tidak ada sintaks untuk menetapkan langsung ke variabel skalar dari OUTPUTklausa.
Martin Smith
3
The OUTPUT klausul memiliki output ke dalam variabel meja atau meja ..
mellamokb
5
The OUTPUTklausul menulis ke sebuah meja. Ini bisa berupa variabel tabel, tabel sementara, ....
HABO
2
Pertanyaan saya secara khusus menanyakan klausa OUTPUT.
Yatrix

Jawaban:

464

Anda dapat memiliki ID yang baru dimasukkan menjadi output ke konsol SSMS seperti ini:

INSERT INTO MyTable(Name, Address, PhoneNo)
OUTPUT INSERTED.ID
VALUES ('Yatrix', '1234 Address Stuff', '1112223333')

Anda dapat menggunakan ini juga dari misalnya C #, ketika Anda perlu mendapatkan ID kembali ke aplikasi panggilan Anda - jalankan saja query SQL dengan .ExecuteScalar()(bukan .ExecuteNonQuery()) untuk membaca IDkembali hasilnya .

Atau jika Anda perlu menangkap IDT-SQL yang baru dimasukkan (misalnya untuk diproses lebih lanjut), Anda perlu membuat variabel tabel:

DECLARE @OutputTbl TABLE (ID INT)

INSERT INTO MyTable(Name, Address, PhoneNo)
OUTPUT INSERTED.ID INTO @OutputTbl(ID)
VALUES ('Yatrix', '1234 Address Stuff', '1112223333')

Dengan cara ini, Anda dapat memasukkan beberapa nilai ke dalam @OutputTbldan melakukan pemrosesan lebih lanjut pada nilai-nilai itu. Anda juga bisa menggunakan tabel sementara "biasa" ( #temp) atau bahkan tabel persisten "nyata" sebagai "target keluaran" Anda di sini.

marc_s
sumber
2
Jawaban di sini untuk kode di belakang singkat. ExecuteScalar () FTW
Joe Johnston
10
Anda dapat memasukkan hasilnya dalam real persistent table- ini sangat fantastis karena itu berarti Anda dapat INSERTinformasi dalam TWOtabel pada saat yang bersamaan.
Gotqn
7
Jangan pernah menggunakan @@ IDENTITY untuk menarik dari atas. Bersikap keras terhadap kerja keras dengan pemicu dan karena mereka merekam riwayat perubahan yang dibuat pada satu tabel dan menyisipkan ke dalam tabel baru pada saat yang sama @@ IDENTITY mulai mengembalikan nilai dari tabel histori. keriuhan terjadi kemudian dari sana! Silakan gunakan solusi marc_s. untuk saat ini saya menggunakan metode @OutputTbl, tapi saya tertarik dengan opsi lain.
Eric Bishard
4
OUTPUT INTO sangat luar biasa kecuali bahwa "Tabel target klausa OUTPUT INTO tidak dapat berada di kedua sisi hubungan (kunci primer, kunci asing)", yang bagi saya adalah sekitar 99% dari kasus penggunaan potensial. Saya berasumsi ini karena klausa OUTPUT dapat mengembalikan data bahkan ketika transaksi dibatalkan, tapi itu agak menjengkelkan sehingga sangat sulit untuk memasukkan data ke dalam tabel terkait A dan B dalam satu kesempatan.
Robert Calhoun
3
@EricBishard SCOPE_IDENTITY()bekerja lebih baik untuk itu.
Derreck Dean