當(dāng)前位置:首頁(yè) >  站長(zhǎng) >  數(shù)據(jù)庫(kù) >  正文

@@IDENTITY與SCOPE_IDENTITY()

 2020-10-21 15:23  來(lái)源: 腳本之家   我來(lái)投稿 撤稿糾錯(cuò)

  域名預(yù)訂/競(jìng)價(jià),好“米”不錯(cuò)過(guò)

在一條 INSERT、SELECT INTO 或大容量復(fù)制語(yǔ)句完成后,@@IDENTITY 中包含語(yǔ)句生成的最后一個(gè)標(biāo)識(shí)值

在一條 INSERT、SELECT INTO 或大容量復(fù)制語(yǔ)句完成后,@@IDENTITY 中包含語(yǔ)句生成的最后一個(gè)標(biāo)識(shí)值。如果語(yǔ)句未影響任何包含標(biāo)識(shí)列的表,則 @@IDENTITY 返回 NULL。如果插入了多個(gè)行,生成了多個(gè)標(biāo)識(shí)值,則 @@IDENTITY 將返回最后生成的標(biāo)識(shí)值。如果語(yǔ)句觸發(fā)了一個(gè)或多個(gè)觸發(fā)器,該觸發(fā)器又執(zhí)行了生成標(biāo)識(shí)值的插入操作,那么,在語(yǔ)句執(zhí)行后立即調(diào)用 @@IDENTITY 將返回觸發(fā)器生成的最后一個(gè)標(biāo)識(shí)值。如果對(duì)包含標(biāo)識(shí)列的表執(zhí)行插入操作后觸發(fā)了觸發(fā)器,并且觸發(fā)器對(duì)另一個(gè)沒(méi)有標(biāo)識(shí)列的表執(zhí)行了插入操作,則 @@IDENTITY 將返回第一次插入的標(biāo)識(shí)值。出現(xiàn) INSERT 或 SELECT INTO 語(yǔ)句失敗或大容量復(fù)制失敗,或者事務(wù)被回滾的情況時(shí),@@IDENTITY 值不會(huì)恢復(fù)為以前的設(shè)置。

如果語(yǔ)句和事務(wù)失敗,它們會(huì)更改表的當(dāng)前標(biāo)識(shí),從而使標(biāo)識(shí)列中的值出現(xiàn)不連貫現(xiàn)象。即使未提交試圖向表中插入值的事務(wù),也永遠(yuǎn)無(wú)法回滾標(biāo)識(shí)值。例如,如果因 IGNORE_DUP_KEY 沖突而導(dǎo)致 INSERT 語(yǔ)句失敗,表的當(dāng)前標(biāo)識(shí)值仍然會(huì)增加。

@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 是相似的函數(shù),因?yàn)樗麄兌挤祷夭迦氲奖淼?IDENTITY 列的最后一個(gè)值。

@@IDENTITY 和 SCOPE_IDENTITY 可以返回當(dāng)前會(huì)話中的所有表中生成的最后一個(gè)標(biāo)識(shí)值。但是,SCOPE_IDENTITY 只在當(dāng)前作用域內(nèi)返回值,而 @@IDENTITY 不限于特定的作用域。

IDENT_CURRENT 不受作用域和會(huì)話的限制,而受限于指定的表。IDENT_CURRENT 可以返回任何會(huì)話和任何作用域中為特定表生成的標(biāo)識(shí)值。

@@IDENTITY 函數(shù)的作用域是執(zhí)行該函數(shù)的本地服務(wù)器上的當(dāng)前會(huì)話。此函數(shù)不能應(yīng)用于遠(yuǎn)程或鏈接服務(wù)器。若要獲得其他服務(wù)器上的標(biāo)識(shí)值,請(qǐng)?jiān)谶h(yuǎn)程服務(wù)器或鏈接服務(wù)器上執(zhí)行存儲(chǔ)過(guò)程,并使(在遠(yuǎn)程或鏈接服務(wù)器的環(huán)境中執(zhí)行的)該存儲(chǔ)過(guò)程收集標(biāo)識(shí)值,并將其返回本地服務(wù)器上的發(fā)出調(diào)用的連接。

以下示例向包含標(biāo)識(shí)列 (LocationID) 的表中插入一行,并使用 @@IDENTITY 顯示新行中使用的標(biāo)識(shí)值:


USE AdventureWorks;
GO
--Display the value of LocationID in the last row in the table.
SELECT MAX(LocationID) FROM Production.Location;
GO
INSERT INTO Production.Location (Name, CostRate, Availability, ModifiedDate)
VALUES ('Damaged Goods', 5, 2.5, GETDATE());
GO
SELECT @@IDENTITY AS 'Identity';
GO
--Display the value of LocationID of the newly inserted row.
SELECT MAX(LocationID) FROM Production.Location;
GO

補(bǔ)充:   我們要慎用@@IDENTITY,原因是 @@IDENTITY 它總是獲取最后一條變更數(shù)據(jù)的自增字段的值,

而忽略了進(jìn)行變更操作所在的范圍約束。比如,我有表 A 和表 B 兩個(gè)表,現(xiàn)在我在表 A 上定義了一個(gè)Insert觸發(fā)器,當(dāng)在表 A 中插入一條數(shù)據(jù)時(shí),自動(dòng)在表 B 也插入一條數(shù)據(jù)。此時(shí),大家注意,有兩個(gè)原子操作:在A中插入一條數(shù)據(jù), 接著在B中隨后插入一條數(shù)據(jù)。

現(xiàn)在我們想下,假設(shè)上面表 A 和表 B 都有IDENTITY自增域,那么我們?cè)诒?A 插入一條數(shù)據(jù)后,使用了 SELECT @@IDENTITY 輸出時(shí),輸出的到底是 A 還是 B 的自增域的值呢? 答案很明顯,是誰(shuí)最后插入就輸出誰(shuí),那么就是 B 了。于是,我本意是想得到 A 的自增域值,結(jié)果得到了 B 的自增域值,一只 BUG 隨之誕生,搞不好還會(huì)影響到整個(gè)系統(tǒng)數(shù)據(jù)的混亂。

因此,對(duì)于這種情況,建議大家慎用 @@IDENTITY,而盡量采用 SCOPE_IDENTITY()函數(shù)替換之。SCOPE_IDENTITY() 也是得到最后一條自增域的值,但是它是僅限在一個(gè)操作范圍之內(nèi),而不@@IDENTITY 是取全局操作的最后一步操作所產(chǎn)生的自增域的值的。

本文來(lái)自腳本之家,原文鏈接:https://www.jb51.net/article/31770.htm

申請(qǐng)創(chuàng)業(yè)報(bào)道,分享創(chuàng)業(yè)好點(diǎn)子。點(diǎn)擊此處,共同探討創(chuàng)業(yè)新機(jī)遇!

相關(guān)標(biāo)簽
@@IDENTITY
SCOPE_IDENTITY()

相關(guān)文章

熱門排行

信息推薦