Mana yang merupakan opsi terbaik untuk mendapatkan nilai identitas yang baru saja saya buat melalui sisipan? Apa dampak dari pernyataan ini dalam hal kinerja?
SCOPE_IDENTITY()
- Fungsi agregat
MAX()
- SELECT
TOP 1
IdentityColumn DARI TableNameORDER BY IdentityColumn DESC
Jawaban:
Gunakan
SCOPE_IDENTITY()
jika Anda memasukkan satu baris dan ingin mengambil ID yang dihasilkan.Hasil:
Gunakan
OUTPUT
klausa jika Anda memasukkan banyak baris dan perlu mengambil set ID yang dihasilkan.Hasil:
Selain kinerja, ini adalah satu-satunya yang dijamin benar di tingkat isolasi standar dan / atau dengan banyak pengguna. Bahkan jika Anda mengabaikan aspek kebenaran, SQL Server menyimpan nilai yang dimasukkan
SCOPE_IDENTITY()
dalam memori, jadi tentu saja ini akan lebih cepat daripada pergi dan menjalankan kueri terisolasi Anda sendiri terhadap tabel atau terhadap tabel sistem.Mengabaikan aspek kebenarannya seperti memberi tahu tukang pos bahwa ia melakukan pekerjaannya dengan baik dengan mengirimkan surat hari ini - ia menyelesaikan rutenya 10 menit lebih cepat dari waktu rata-rata, masalahnya adalah, tidak ada surat yang dikirim ke rumah yang tepat.
Jangan gunakan salah satu dari yang berikut:
@@IDENTITY
- karena ini tidak dapat digunakan di semua skenario, misalnya ketika tabel dengan kolom identitas memiliki pemicu yang juga menyisipkan ke tabel lain dengan kolom identitasnya sendiri - Anda akan mendapatkan nilai yang salah kembali.IDENT_CURRENT()
- Saya menjelaskan secara terperinci tentang hal ini di sini , dan komentar-komentarnya juga bermanfaat untuk dibaca, tetapi pada dasarnya, di bawah konkurensi, Anda akan sering mendapatkan jawaban yang salah.MAX()
atauTOP 1
- Anda harus melindungi kedua pernyataan dengan isolasi serializable untuk memastikan bahwa yangMAX()
Anda dapatkan bukan milik orang lain. Ini jauh lebih mahal daripada hanya menggunakanSCOPE_IDENTITY()
.Fungsi-fungsi ini juga gagal setiap kali Anda memasukkan dua baris atau lebih, dan membutuhkan semua nilai identitas yang dihasilkan - satu-satunya pilihan Anda ada
OUTPUT
klausa.sumber
Terlepas dari kinerja, mereka semua memiliki makna yang agak berbeda.
SCOPE_IDENTITY()
akan memberi Anda nilai identitas terakhir yang dimasukkan ke dalam tabel apa pun secara langsung dalam lingkup saat ini (lingkup = kumpulan, prosedur tersimpan, dll. tetapi tidak di dalam, katakanlah, pemicu yang dipicu oleh cakupan saat ini).IDENT_CURRENT()
akan memberi Anda nilai identitas terakhir yang dimasukkan ke tabel tertentu dari ruang lingkup apa pun , oleh pengguna mana pun .@@IDENTITY
memberi Anda nilai identitas terakhir yang dihasilkan oleh pernyataan INSERT terbaru untuk koneksi saat ini, terlepas dari tabel atau ruang lingkup. (Catatan: Akses menggunakan fungsi ini, dan karenanya memiliki beberapa masalah dengan pemicu yang memasukkan nilai ke dalam tabel dengan kolom identitas.)Menggunakan
MAX()
atauTOP 1
dapat memberi Anda hasil yang sepenuhnya salah jika tabel memiliki langkah identitas negatif, atau baris-baris yang dimasukkanSET IDENTITY_INSERT
dalam permainan. Berikut ini skrip yang menunjukkan semua ini:Ringkasan: tetap dengan
SCOPE_IDENTITY()
,,IDENT_CURRENT()
atau@@IDENTITY
, dan pastikan Anda menggunakan yang mengembalikan apa yang sebenarnya Anda butuhkan.sumber
IDENT_CURRENT()
dan@@IDENTITY
ketika skrip Anda sendiri menunjukkan bahwa mereka menghasilkan hasil yang salah?IDENT_CURRENT()
mengembalikan. MAX () tidak pernah mengembalikan nilai yang tepat di luar baris pertama, karena id menghitung mundur, dan denganIDENTITY_INSERT
pada, 9005 bukan nilai identitas yang dihasilkan , sehingga tidak tercermin olehIDENT_CURRENT()
. Tapi itu mungkin mengembalikan hasil "salah" jika Anda benar-benar setelah apa yangSCOPE_IDENTITY()
kembali. Pilih alat yang tepat untuk pekerjaan itu.@@IDENTITY
hampir tidak pernah cara yang ideal untuk mendapatkan nilai-nilai identitas yang dihasilkan. Poin utama adalah bahwaMAX()
atauTOP 1
seperti versi yang kurang dapat diandalkanIDENT_CURRENT()
, yang merupakan fungsi yang sangat baik untuk digunakan jika Anda mengerti apa yang dilakukannya. Bisa berguna untuk pekerjaan pemeliharaan atau semacamnya.