Apa perbedaan antara Scope_Identity (), Identity (), @@ Identity, dan Ident_Current ()?

192

Aku tahu Scope_Identity(), Identity(), @@Identity, dan Ident_Current()semua mendapatkan nilai dari kolom identitas, tapi aku akan senang untuk mengetahui perbedaannya.

Bagian dari kontroversi yang saya alami adalah apa yang mereka maksud dengan ruang lingkup sebagaimana diterapkan pada fungsi-fungsi di atas?

Saya juga akan menyukai contoh sederhana dari berbagai skenario penggunaannya?

Tebo
sumber
2
Jangan lupa tentang bug eksekusi paralel yang ada di SQL Server untuk SCOPE_IDENTITY dan @@ IDENTITY: support.microsoft.com/default.aspx?scid=kb;en-US;2019779
David
@DaviddCeFreitas - Saya penasaran untuk membaca tentang bug, tetapi tautannya tampaknya rusak (atau setidaknya, itu melempar kesalahan ASP).
rory.ap
2
Sebenarnya, saya menemukannya: support.microsoft.com/en-us/kb/2019779
rory.ap
Fix telah dirilis sebagaimana disebutkan di artikel KB lama itu
George Birbilis

Jawaban:

396
  • The @@identitymengembalikan fungsi identitas terakhir dibuat dalam sesi yang sama.
  • The scope_identity()mengembalikan fungsi identitas terakhir dibuat dalam sesi yang sama dan ruang lingkup yang sama.
  • The ident_current(name)mengembalikan identitas terakhir yang dibuat untuk meja tertentu atau melihat di setiap sesi.
  • The identity()Fungsi tidak digunakan untuk mendapatkan identitas, itu digunakan untuk membuat identitas dalam select...intoquery.

Sesi ini adalah koneksi basis data. Ruang lingkup adalah kueri saat ini atau prosedur tersimpan saat ini.

Sebuah situasi di mana scope_identity()dan @@identityfungsi berbeda, adalah jika Anda memiliki pemicu di atas meja. Jika Anda memiliki kueri yang menyisipkan catatan, menyebabkan pelat untuk menyisipkan catatan lain di suatu tempat, scope_identity()fungsi akan mengembalikan identitas yang dibuat oleh permintaan, sementara @@identityfungsi akan mengembalikan identitas yang dibuat oleh pelatuk.

Jadi, biasanya Anda akan menggunakan scope_identity()fungsinya.

Guffa
sumber
14
Saya memilih ini sebagai jawabannya, karena paragraf "Situasi di mana paragraf scope_identity () dan @@ identitas ...". Ini menjelaskan lebih banyak hal.
Tebo,
1
Seperti yang David Freitas sebutkan di atas, ada bug dalam implementasi scope_identity, jadi saya merekomendasikan untuk menggunakan metode alternatif, klausa OUTPUT. Lihat jawaban saya di bawah ini.
Sebastian Meine
@Guffa - "Sesi ini adalah koneksi basis data". Apakah sesi dikelola di seluruh koneksi jika Anda menggunakan Connection Pooling?
Dave Black
1
Ini adalah jawaban panutan. Secara khusus, bekerja dengan SQL dan SQL Server bisa aneh, dan ini menjelaskan hal-hal dengan cara yang sangat jelas, awam, sementara masih cukup informatif. Itu tidak terdengar seperti sesuatu yang dikomunikasikan antara dua spesialis basis data, yang BANYAK jawaban SE lainnya lakukan.
Panzercrisis
@DaveBlack dari apa yang saya baca: Tidak, sesi tidak dikelola di pool, sesi unik untuk skrip Anda setelah terhubung (). Saat menggabungkan ... PHP untuk SQL Server menggunakan penggabungan koneksi ODBC. Saat koneksi dari pool digunakan, status koneksi diatur ulang. Menutup koneksi mengembalikan koneksi ke pool. (catatan: lihat komentar untuk linux / mac) docs.microsoft.com/en-us/sql/connect/php/…
GDmac
42

Pertanyaan bagus.

  • @@IDENTITY: mengembalikan nilai identitas terakhir yang dihasilkan pada koneksi SQL Anda (SPID). Sebagian besar waktu akan menjadi apa yang Anda inginkan, tetapi kadang-kadang tidak (seperti ketika pemicu dipecat sebagai respons terhadap INSERT, dan pemicu mengeksekusi INSERTpernyataan lain ).

  • SCOPE_IDENTITY(): mengembalikan nilai identitas terakhir yang dihasilkan dalam lingkup saat ini (yaitu prosedur tersimpan, pemicu, fungsi, dll).

  • IDENT_CURRENT(): mengembalikan nilai identitas terakhir untuk tabel tertentu. Jangan gunakan ini untuk mendapatkan nilai identitas dari INSERT, itu tunduk pada kondisi ras (yaitu beberapa koneksi menyisipkan baris pada tabel yang sama).

  • IDENTITY(): digunakan saat mendeklarasikan kolom dalam tabel sebagai kolom identitas.

Untuk referensi lebih lanjut, lihat: http://msdn.microsoft.com/en-us/library/ms187342.aspx .

Untuk meringkas: jika Anda memasukkan baris, dan Anda ingin tahu nilai kolom identitas untuk baris yang baru saja Anda masukkan, selalu gunakan SCOPE_IDENTITY().

Brannon
sumber
16

Jika Anda memahami perbedaan antara ruang lingkup dan sesi maka akan sangat mudah untuk memahami metode ini.

Posting blog yang sangat bagus oleh Adam Anderson menjelaskan perbedaan ini:

Sesi berarti koneksi saat ini yang menjalankan perintah.

Lingkup berarti konteks langsung dari suatu perintah. Setiap panggilan prosedur yang tersimpan dijalankan dalam ruang lingkupnya sendiri, dan panggilan bersarang dijalankan dalam ruang lingkup bersarang dalam ruang lingkup prosedur panggilan. Demikian pula, perintah SQL yang dijalankan dari aplikasi atau SSMS dijalankan dalam cakupannya sendiri, dan jika perintah itu memicu pemicu, setiap pemicu dijalankan dalam cakupan bersarangnya sendiri.

Dengan demikian perbedaan antara tiga metode pengambilan identitas adalah sebagai berikut:

@@identitymengembalikan nilai identitas terakhir yang dihasilkan dalam sesi ini tetapi ruang lingkup apa pun .

scope_identity()mengembalikan nilai identitas terakhir yang dihasilkan dalam ini sesi dan ini ruang lingkup.

ident_current()mengembalikan nilai identitas terakhir yang dihasilkan untuk tabel tertentu dalam setiap sesi dan setiap lingkup.

Hemant Sakta
sumber
11

Lingkup berarti konteks kode yang melakukan INSERTpernyataan SCOPE_IDENTITY(), yang bertentangan dengan lingkup global @@IDENTITY.

CREATE TABLE Foo(
  ID INT IDENTITY(1,1),
  Dummy VARCHAR(100)
)

CREATE TABLE FooLog(
  ID INT IDENTITY(2,2),
  LogText VARCHAR(100)
)
go
CREATE TRIGGER InsertFoo ON Foo AFTER INSERT AS
BEGIN
  INSERT INTO FooLog (LogText) VALUES ('inserted Foo')
  INSERT INTO FooLog (LogText) SELECT Dummy FROM inserted
END

INSERT INTO Foo (Dummy) VALUES ('x')
SELECT SCOPE_IDENTITY(), @@IDENTITY 

Memberikan hasil berbeda.

devio
sumber
6

Untuk mengklarifikasi masalah dengan @@Identity:

Misalnya, jika Anda menyisipkan tabel dan tabel tersebut telah memicu melakukan sisipan, @@Identityakan mengembalikan id dari sisipan di pelatuk (a log_idatau sesuatu), sementara scope_identity()akan mengembalikan id dari sisipan di tabel asli.

Jadi, jika Anda tidak memiliki pemicu, scope_identity()dan @@identityakan mengembalikan nilai yang sama. Jika Anda memiliki pemicu, Anda perlu memikirkan nilai apa yang Anda inginkan.

Jonas Lincoln
sumber
4

Scope Identity: Identitas catatan terakhir ditambahkan dalam prosedur tersimpan yang dijalankan.

@@Identity: Identitas catatan terakhir yang ditambahkan dalam kumpulan kueri, atau sebagai hasil dari kueri, mis. Prosedur yang melakukan penyisipan, pemicu kemudian yang memicu yang kemudian menyisipkan catatan akan mengembalikan identitas catatan yang dimasukkan dari pemicu.

IdentCurrent: Identitas terakhir yang dialokasikan untuk tabel.

Andrew
sumber
3

Berikut ini penjelasan lain dari buku ini :

Adapun perbedaan antara SCOPE_IDENTITY dan @@ IDENTITY, misalkan Anda memiliki prosedur tersimpan P1 dengan tiga pernyataan:
- INSERT yang menghasilkan nilai identitas baru
- Panggilan ke prosedur tersimpan P2 yang juga memiliki pernyataan INSERT yang menghasilkan yang baru nilai identitas
- Pernyataan yang menanyakan fungsi SCOPE_IDENTITY dan @@ IDENTITY Fungsi SCOPE_IDENTITY akan mengembalikan nilai yang dihasilkan oleh P1 (sesi dan ruang lingkup yang sama). Fungsi @@ IDENTITY akan mengembalikan nilai yang dihasilkan oleh P2 (sesi yang sama terlepas dari ruang lingkup).

Dmitriy Dokshin
sumber