Scope_Identity (), Identity (), @@ Identity ve Ident_Current () arasındaki fark nedir?


192

Biliyorum Scope_Identity(), Identity(), @@Identityve Ident_Current()tüm kimlik sütunun değerini almak ama farkı bilmek isteriz.

Yaşadığım tartışmaların bir kısmı, yukarıdaki bu işlevlere uygulandığı şekliyle kapsamla ne anlama geliyor?

Bunları kullanmanın farklı senaryolarının basit bir örneğini de isterim?


2
SCOPE_IDENTITY ve @@ IDENTITY için SQL Server'da bulunan paralel yürütme hatasını unutmayın: support.microsoft.com/default.aspx?scid=kb;en-US;2019779
David d C e Freitas

@DaviddCeFreitas - Hata hakkında merak ediyorum, ancak bağlantı kopmuş gibi görünüyor (veya en azından bir ASP hatası atıyor).
rory.ap


Düzeltme eski KB makalesinde bahsedildiği gibi yayınlandı
George Birbilis

Yanıtlar:


396
  • @@identityFonksiyon aynı oturumda oluşturulan son kimliğini döndürür.
  • scope_identity()Fonksiyon Aynı seansta aynı kapsamda oluşturulan son kimliğini döndürür.
  • ident_current(name)Herhangi bir oturumda, belirli bir tablo veya görünümü için oluşturulan son kimlik döndürür.
  • identity()İşlevi bir de bir kimlik oluşturmak için kullanılan, bir kimlik almak için kullanılmaz select...intosorgusu.

Oturum veritabanı bağlantısıdır. Kapsam geçerli sorgu veya geçerli saklı yordamdır.

scope_identity()Ve @@identityişlevlerinin farklı olduğu bir durum , masada bir tetikleyiciniz varsa. Kayıt ekleyen ve tetikleyicinin başka bir kayıt eklemesine neden olan bir sorgunuz varsa, scope_identity()işlev sorgu @@identitytarafından oluşturulan kimliği döndürürken işlev tetikleyici tarafından oluşturulan kimliği döndürür.

Yani, normalde scope_identity()fonksiyonu kullanırsınız .


14
Bunu "scope_identity () ve @@ identity ..." paragrafının bulunduğu bir durum olarak yanıt olarak seçtim. Her şeyi daha fazla netleştirdi.
Aralık'ta Tebo

1
David Freitas yukarıda belirtildiği gibi, scope_identity uygulanmasında bir hata var, bu yüzden OUTPUT yan tümcesi alternatif bir yöntem kullanmanızı öneririz. Cevabımı aşağıda görebilirsiniz.
Sebastian Meine

@Guffa - "Oturum veritabanı bağlantısıdır". Bağlantı Havuzu Oluşturma kullanıyorsanız oturum bağlantılar arasında korunur mu?
Dave Black

1
Bu bir rol modeli cevabıdır. Özellikle, SQL ve SQL Server ile çalışmak garip olabilir ve bu durum oldukça açık, layman bir şekilde açıklanırken, yine de oldukça bilgilendiricidir. İki veritabanı uzmanı arasında iletilen bir şey gibi görünmüyor, diğer SE cevaplarının bir sürü yaptığı gibi.
Panzercrisis

@DaveBlack okudum ne: Hayır, oturum havuzda korunmaz, oturum connect () sonra komut dosyası çalıştırmak için benzersizdir. Havuz oluştururken ... SQL Server için PHP ODBC bağlantı havuzu kullanır. Havuzdan bir bağlantı kullanıldığında, bağlantı durumu sıfırlanır. Bağlantının kapatılması bağlantıyı havuza döndürür. (not: linux / mac ile ilgili açıklamalara bakın) docs.microsoft.com/en-us/sql/connect/php/…
GDmac

42

İyi soru.

  • @@IDENTITY: SQL bağlantınızda (SPID) oluşturulan son kimlik değerini döndürür. Çoğu zaman istediğiniz şey olacaktır, ancak bazen değil (bir tetikleyiciye yanıt olarak bir INSERTtetikleyici tetiklendiğinde ve tetikleyici başka bir INSERTdeyim çalıştırdığında olduğu gibi ).

  • SCOPE_IDENTITY(): geçerli kapsamda üretilen son kimlik değerini döndürür (yani saklı yordam, tetikleyici, işlev vb.).

  • IDENT_CURRENT(): belirli bir tablonun son kimlik değerini döndürür. Kimlik değerini elde etmek için bunu kullanmayın INSERT, yarış koşullarına tabidir (yani, aynı tabloya satır ekleyen birden fazla bağlantı).

  • IDENTITY(): tablodaki bir sütunu kimlik sütunu olarak bildirirken kullanılır.

Daha fazla referans için bkz . Http://msdn.microsoft.com/en-us/library/ms187342.aspx .

Özetlemek gerekirse: Eğer satırlar ekleyerek edilir ve satır için kimlik sütunun değerini bilmek istiyorsanız size sadece takılı, her zaman kullanın SCOPE_IDENTITY().


16

Kapsam ve oturum arasındaki farkı anlarsanız, bu yöntemleri anlamak çok kolay olacaktır.

Adam Anderson'ın çok güzel bir blog yazısı bu farkı anlatıyor:

Oturum , komutu yürüten geçerli bağlantı anlamına gelir.

Kapsam , bir komutun yakın bağlamı anlamına gelir. Saklanan her yordam çağrısı kendi kapsamında yürütülür ve iç içe çağrılar çağırma yordamı kapsamında iç içe bir kapsamda yürütülür. Benzer şekilde, bir uygulamadan veya SSMS'den yürütülen bir SQL komutu kendi kapsamında yürütülür ve bu komut herhangi bir tetikleyici tetiklerse, her tetikleyici kendi iç içe kapsamı içinde yürütülür.

Dolayısıyla, üç kimlik alma yöntemi arasındaki farklar aşağıdaki gibidir:

@@identitybu oturumda oluşturulan son kimlik değerini ancak herhangi bir kapsamı döndürür .

scope_identity()bu oturumda ve bu kapsamda üretilen son kimlik değerini döndürür .

ident_current()belirli bir tablo için oluşturulan son kimlik değerini verir herhangi bir oturum ve herhangi bir kapsam.


11

Kapsam , genel kapsamının aksine INSERTifadeyi gerçekleştiren kod bağlamı anlamına gelir .SCOPE_IDENTITY()@@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 

Farklı sonuçlar verir.


9

@David Freitas tarafından bahsedilen hata ve 2012 yılında tanıtılan yeni Dizi özelliğinin uyumsuzluğu nedeniyle, bunların üçünden de uzak durmanızı tavsiye ederim. Bunun yerine, eklenen kimlik değerini almak için ÇIKTI yan tümcesini kullanabilirsiniz. Diğer bir avantaj, ÇIKIŞ'ın birden fazla satır eklediyseniz bile çalışmasıdır.

Ayrıntılar ve örnekler için buraya bakın: Kimlik Krizi


Bence bu cevap daha fazla ilgiyi hak ediyor.
Cheeze

Ne yazık ki INSERT ... OUTPUT Inserted.xx, INSERT tetikleyicileri ile çalışmaz (aynı durum UPDATE ... OUTPUT Updated.xx ve UPDATE tetikleyicileri için de geçerlidir). INSERT ... OUTPUT INTO kullanılmasını önerirler, ancak çok ayrıntılıdır ve istemcilerden (saklanan procs yerine) bunu kullanmak sorunludur. INSERT ... OUTPUT Tetikleyicilere ihtiyacınız yoksa, Inserted.xx istemci tarafı çağrıları ile kullanıldığında güzeldir (ekleme yapmak ve yeni satır için otomatik oluşturulan kimliği geri almak için bir ExecuteScalar'a ihtiyacınız var).
George Birbilis

Bu hata düzeltildi mi? bu makalenin yazılmasından bu yana 8 yıl geçti
dopatraman

6

Sorunu açıklığa kavuşturmak için @@Identity:

Örneğin, bir tablo eklerseniz ve bu tablonun ekler yapan tetikleyicileri varsa @@Identity, kimliği tetikleyicideki ekten (a log_idveya başka bir şey) scope_identity()döndürürken, kimliği orijinal tablodaki ekten döndürür.

Eğer herhangi bir tetikleyici yoktur, Yani scope_identity()ve @@identityaynı değeri döndürecektir. Tetikleyicileriniz varsa, hangi değeri istediğinizi düşünmeniz gerekir.


4

Scope Identity: Yürütülen saklı yordam içine eklenen son kaydın kimliği.

@@Identity: Sorgu toplu işine eklenen son kaydın kimliği veya sorgunun sonucu olarak, örneğin bir ekleme yapan bir yordamın ardından, daha sonra bir kayıt ekleyen bir tetikleyici tetikler, eklenen kaydın kimliğini tetikleyiciden döndürür.

IdentCurrent: Tablo için ayrılan son kimlik.


3

İşte kitaptan bir başka iyi açıklama :

SCOPE_IDENTITY ve @@ IDENTITY arasındaki farka gelince, üç ifadeli bir saklı yordam P1'e sahip olduğunuzu varsayalım:
- Yeni bir kimlik değeri üreten bir INSERT - Yeni
bir yaratan bir INSERT ifadesine sahip bir saklı yordam P2'ye çağrı identity value
- SCOPE_IDENTITY ve @@ IDENTITY işlevlerini sorgulayan bir ifade SCOPE_IDENTITY işlevi P1 (aynı oturum ve kapsam) tarafından üretilen değeri döndürür. @@ IDENTITY işlevi P2 tarafından üretilen değeri döndürür (kapsamdan bağımsız olarak aynı oturum).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.