Apa cara terbaik untuk mendapatkan IDENTITY
baris yang disisipkan?
Saya tahu tentang @@IDENTITY
dan IDENT_CURRENT
dan SCOPE_IDENTITY
tetapi tidak mengerti pro dan kontra yang melekat pada masing-masing.
Bisakah seseorang menjelaskan perbedaannya dan kapan saya harus menggunakannya?
sql
sql-server
tsql
Oded
sumber
sumber
INSERT INTO Table1(fields...) OUTPUT INSERTED.id VALUES (...)
, atau metode yang lebih lama:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();
Anda bisa mendapatkannya di c # menggunakan ExecuteScalar ().OUTPUT
klausa di SQL Server.Jawaban:
@@IDENTITY
mengembalikan nilai identitas terakhir yang dihasilkan untuk tabel apa pun di sesi saat ini, di semua lingkup. Anda harus berhati-hati di sini , karena melintasi batas. Anda bisa mendapatkan nilai dari pemicu, alih-alih pernyataan Anda saat ini.SCOPE_IDENTITY()
mengembalikan nilai identitas terakhir yang dihasilkan untuk tabel apa pun di sesi saat ini dan ruang lingkup saat ini. Umumnya apa yang ingin Anda gunakan .IDENT_CURRENT('tableName')
mengembalikan nilai identitas terakhir yang dihasilkan untuk tabel tertentu di sesi apa pun dan ruang lingkup apa pun. Ini memungkinkan Anda menentukan tabel mana yang Anda inginkan nilainya, jika kedua di atas tidak cukup yang Anda butuhkan ( sangat jarang ). Juga, seperti yang dikatakan @ Guy Starbuck , "Anda bisa menggunakan ini jika Anda ingin mendapatkan nilai IDENTITAS saat ini untuk tabel yang belum Anda masukkan catatannya."The
OUTPUT
klausul dariINSERT
pernyataan akan membiarkan Anda mengakses setiap baris yang dimasukkan melalui pernyataan itu. Karena ini mencakup pernyataan spesifik, itu lebih mudah daripada fungsi-fungsi lain di atas. Namun, ini sedikit lebih bertele-tele (Anda harus memasukkan ke dalam tabel variabel / tabel temp dan kemudian query itu) dan itu memberikan hasil bahkan dalam skenario kesalahan di mana pernyataan tersebut dibatalkan. Yang mengatakan, jika permintaan Anda menggunakan rencana eksekusi paralel, ini adalah satu - satunya metode yang dijamin untuk mendapatkan identitas (singkat mematikan paralelisme). Namun, ini dieksekusi sebelum pemicu dan tidak dapat digunakan untuk mengembalikan nilai yang dihasilkan pemicu.sumber
output
Anda tidak perlu membuat tabel temp untuk menyimpan dan meminta hasil. Biarkan sajainto
bagian klausa output dan itu akan menampilkannya ke resultset.OUTPUT
"terbaik" selama Anda tidak menggunakan pemicu dan menangani kesalahan, tetapiSCOPE_IDENTITY
merupakan masalah yang paling sederhana dan sangat jarang terjadiSaya percaya metode paling aman dan paling akurat untuk mengambil id yang dimasukkan akan menggunakan klausa keluaran.
misalnya (diambil dari artikel MSDN berikut )
sumber
OUTPUT
di SQL Server 2005 , jadi sepertinya itu hanya SQL Server 2000 dan sebelumnya yang tanpa ituSaya mengatakan hal yang sama dengan yang lain, jadi semua orang benar, saya hanya berusaha membuatnya lebih jelas.
@@IDENTITY
mengembalikan id dari hal terakhir yang dimasukkan oleh koneksi klien Anda ke database.Sebagian besar waktu ini berfungsi dengan baik, tetapi kadang-kadang pemicu akan pergi dan menyisipkan baris baru yang tidak Anda ketahui, dan Anda akan mendapatkan ID dari baris baru ini, bukan yang Anda inginkan
SCOPE_IDENTITY()
memecahkan masalah ini. Ia mengembalikan id dari hal terakhir yang Anda masukkan dalam kode SQL yang Anda kirim ke database. Jika pemicu pergi dan membuat baris tambahan, mereka tidak akan menyebabkan nilai yang salah untuk dikembalikan. HoreIDENT_CURRENT
mengembalikan ID terakhir yang dimasukkan oleh siapa pun. Jika beberapa aplikasi lain memasukkan baris lain pada waktu yang tidak diinginkan, Anda akan mendapatkan ID baris itu dan bukan baris Anda.Jika Anda ingin bermain aman, selalu gunakan
SCOPE_IDENTITY()
. Jika Anda tetap dengan@@IDENTITY
dan seseorang memutuskan untuk menambahkan pemicu nanti, semua kode Anda akan rusak.sumber
Cara terbaik (baca: paling aman) untuk mendapatkan identitas dari baris yang baru dimasukkan adalah dengan menggunakan
output
klausa:sumber
scope_identity()
) untuk mendapatkan paket paralel. Dan bug ini diperbaiki lebih dari setahun sebelum jawaban ini.output
bukanscope_identity()
. Saya telah menghapus FUD tentang pengelompokan dalam jawaban.Menambahkan
ke akhir pernyataan sql insert Anda, lalu
akan mengambilnya.
sumber
Saat Anda menggunakan Entity Framework, secara internal menggunakan
OUTPUT
teknik untuk mengembalikan nilai ID yang baru saja dimasukkanHasil output disimpan dalam variabel tabel sementara, bergabung kembali ke tabel, dan mengembalikan nilai baris dari tabel.
Catatan: Saya tidak tahu mengapa EF akan bergabung dengan tabel ephemeral kembali ke meja nyata (dalam keadaan apa keduanya tidak cocok).
Tapi itulah yang dilakukan EF.
Teknik ini (
OUTPUT
) hanya tersedia di SQL Server 2008 atau lebih baru.Sunting - Alasan untuk bergabung
Alasan Kerangka Entity bergabung kembali ke tabel asli, daripada hanya menggunakan
OUTPUT
nilai adalah karena EF juga menggunakan teknik ini untuk mendapatkanrowversion
baris baru yang dimasukkan.Anda dapat menggunakan konkurensi optimis dalam model kerangka entitas Anda dengan menggunakan
Timestamp
atribut: 🕗Saat Anda melakukan ini, Entity Framework akan membutuhkan baris
rowversion
yang baru dimasukkan:Dan untuk mengambil ini,
Timetsamp
Anda tidak dapat menggunakanOUTPUT
klausa.Itu karena jika ada pemicu di atas meja, apa pun yang
Timestamp
Anda OUTPUT akan salah:Stempel waktu yang dikembalikan tidak akan pernah benar jika Anda memiliki pemicu di atas meja. Jadi, Anda harus menggunakan yang terpisah
SELECT
.Dan bahkan jika Anda bersedia untuk menderita versi row salah, alasan lain untuk melakukan terpisah
SELECT
adalah bahwa Anda tidak dapat OUTPUTrowversion
menjadi variabel tabel:Alasan ketiga untuk melakukannya adalah karena simetri. Saat melakukan
UPDATE
di atas meja dengan pemicu, Anda tidak bisa menggunakanOUTPUT
klausa. Mencoba melakukannyaUPDATE
denganOUTPUT
tidak didukung, dan akan memberikan kesalahan:Satu-satunya cara untuk melakukannya adalah dengan pernyataan tindak lanjut
SELECT
:sumber
TurboEncabulators
:) :)MSDN
sumber
@@ IDENTITY adalah identitas terakhir yang dimasukkan menggunakan SQL Connection saat ini. Ini adalah nilai yang baik untuk kembali dari prosedur tersimpan yang disisipkan, di mana Anda hanya perlu identitas dimasukkan untuk catatan baru Anda, dan tidak peduli jika lebih banyak baris ditambahkan sesudahnya.
SCOPE_IDENTITY adalah identitas terakhir yang disisipkan menggunakan SQL Connection saat ini, dan dalam lingkup saat ini - yaitu, jika ada IDENTITY kedua yang dimasukkan berdasarkan pemicu setelah penyisipan Anda, itu tidak akan tercermin dalam SCOPE_IDENTITY, hanya penyisipan yang Anda lakukan . Terus terang, saya tidak pernah punya alasan untuk menggunakan ini.
IDENT_CURRENT (tablename) adalah identitas terakhir yang dimasukkan terlepas dari koneksi atau cakupannya. Anda bisa menggunakan ini jika Anda ingin mendapatkan nilai IDENTITAS saat ini untuk tabel yang Anda belum memasukkan catatan.
sumber
Saya tidak dapat berbicara dengan versi lain dari SQL Server, tetapi pada tahun 2012, keluaran langsung berfungsi dengan baik. Anda tidak perlu repot dengan meja sementara.
Ngomong-ngomong, teknik ini juga berfungsi saat memasukkan banyak baris.
Keluaran
sumber
OUTPUT
. Jika Anda tidak memerlukan tabel temp, maka kueri Anda menjadi jauh lebih sederhana.SELALU menggunakan scope_identity (), TIDAK PERNAH ada kebutuhan untuk hal lain.
sumber
Buat
uuid
dan masukkan juga ke kolom. Maka Anda dapat dengan mudah mengidentifikasi baris Anda dengan uuid. Itulah satu-satunya solusi kerja 100% yang dapat Anda terapkan. Semua solusi lain terlalu rumit atau tidak berfungsi dalam kasus tepi yang sama. Misalnya:1) Buat baris
2) Dapatkan baris yang dibuat
sumber
uuid
di database. Jadi baris akan ditemukan lebih cepat.https://www.npmjs.com/package/uuid
.const uuidv4 = require('uuid/v4'); const uuid = uuidv4()
Salah satu cara lain untuk menjamin identitas baris yang Anda masukkan adalah dengan menentukan nilai identitas dan menggunakan
SET IDENTITY_INSERT ON
dan kemudianOFF
. Ini menjamin Anda tahu persis apa nilai identitas itu! Selama nilainya tidak digunakan maka Anda dapat memasukkan nilai-nilai ini ke dalam kolom identitas.Ini bisa menjadi teknik yang sangat berguna jika Anda memuat data dari sumber lain atau menggabungkan data dari dua basis data dll.
sumber
Meskipun ini adalah utas yang lebih lama, ada cara yang lebih baru untuk melakukan ini yang menghindari beberapa jebakan kolom IDENTITAS dalam versi SQL Server yang lebih lama, seperti celah dalam nilai identitas setelah server dinyalakan ulang . Urutan tersedia di SQL Server 2016 dan maju yang merupakan cara yang lebih baru adalah membuat objek URUTAN menggunakan TSQL. Ini memungkinkan Anda membuat objek urutan numerik Anda sendiri di SQL Server dan mengontrol bagaimana itu bertambah.
Berikut ini sebuah contoh:
Kemudian di TSQL Anda akan melakukan hal berikut untuk mendapatkan ID urutan berikutnya:
Berikut adalah tautan ke CREATE SEQUENCE dan VALUE FOR NEXT FOR
sumber
Setelah Pernyataan Sisipan Anda, Anda perlu menambahkan ini. Dan Pastikan tentang nama tabel tempat memasukkan data. Anda akan mendapatkan baris saat ini tidak di mana baris dipengaruhi oleh pernyataan sisipan Anda.
sumber