Az önce oluşturduğum kimlik değerini bir ekleme yoluyla almak için en iyi seçenek hangisidir? Bu ifadelerin performans açısından etkisi nedir?
SCOPE_IDENTITY()
MAX()
TOP 1
IdentityColumn FROM TableName ORDER BY IdentityColumn DESC
Tek bir satır ekliyorsanız ve oluşturulan kimliği almak istiyorsanız SCOPE_IDENTITY()
işlevini kullanın.
CREATE TABLE #a(identity_column INT IDENTITY(1,1), x CHAR(1));
INSERT #a(x) VALUES('a');
SELECT SCOPE_IDENTITY();
Sonuç:
----
1
Birden fazla satır ekliyorsanız ve oluşturulan kimliklerin kümesini almanız gerekiyorsa OUTPUT
cümlesini kullanın.
INSERT #a(x)
OUTPUT inserted.identity_column
VALUES('b'),('c');
Sonuç:
----
2
3
ve neden bu en hızlı seçenek?
Performans bir yana, varsayılan izolasyon seviyesinde ve/veya birden fazla kullanıcı ile doğru olması garanti edilenler yalnızca bunlardır. Doğruluk yönünü göz ardı etseniz bile, SQL Server eklenen değeri SCOPE_IDENTITY()
içinde bellekte tutar, bu nedenle doğal olarak bu, tabloya veya sistem tablolarına karşı kendi yalıtılmış sorgunuzu çalıştırmaktan daha hızlı olacaktır.
Doğruluk unsurunu göz ardı etmek, postacıya bugün postaları teslim ederken iyi iş çıkardığını söylemek gibidir - rotasını ortalama süresinden 10 dakika daha hızlı bitirmiştir, sorun şu ki, postaların hiçbiri doğru eve teslim edilmemiştir.
Aşağıdakilerden herhangi birini kullanmayın:
MAX()
veya TOP 1
- aldığınız MAX()
ın başkasına ait olmadığından emin olmak için iki deyimi serileştirilebilir izolasyon ile korumanız gerekir. Bu, sadece SCOPE_IDENTITY()
kullanmaktan çok daha pahalıdır.Bu işlevler, iki veya daha fazla satır eklediğinizde ve oluşturulan tüm kimlik değerlerine ihtiyaç duyduğunuzda da başarısız olur - buradaki tek seçeneğiniz OUTPUT
cümlesidir.
Performans dışında, hepsinin oldukça farklı anlamları vardır.
SCOPE_IDENTITY()` size doğrudan geçerli kapsam içinde herhangi bir tabloya eklenen son kimlik değerini verecektir (kapsam = toplu iş, saklı yordam, vb. ancak geçerli kapsam tarafından ateşlenen bir tetikleyici içinde değil).
IDENT_CURRENT()` size herhangi bir kapsamdan, herhangi bir kullanıcı tarafından belirli bir tabloya eklenen son kimlik değerini verecektir.
@@IDENTITY`, tablo veya kapsamdan bağımsız olarak, geçerli bağlantı için en son INSERT deyimi tarafından oluşturulan son kimlik değerini verir. (Yan not: Access bu işlevi kullanır ve bu nedenle kimlik sütunları olan tablolara değer ekleyen tetikleyicilerle ilgili bazı sorunlar vardır).
Tabloda negatif kimlik adımı varsa veya SET IDENTITY_INSERT
ile satır eklenmişse MAX()
veya TOP 1
kullanmak size tamamen yanlış sonuçlar verebilir. İşte tüm bunları gösteren bir komut dosyası:
CREATE TABLE ReverseIdent (
id int IDENTITY(9000,-1) NOT NULL PRIMARY KEY CLUSTERED,
data char(4)
)
INSERT INTO ReverseIdent (data)
VALUES ('a'), ('b'), ('c')
SELECT * FROM ReverseIdent
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9000
SET IDENTITY_INSERT ReverseIdent ON
INSERT INTO ReverseIdent (id, data)
VALUES (9005, 'd')
SET IDENTITY_INSERT ReverseIdent OFF
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9005
Özet: SCOPE_IDENTITY()
, IDENT_CURRENT()
veya @@IDENTITY
ile devam edin ve gerçekten ihtiyacınız olanı döndüreni kullandığınızdan emin olun.