SQL SERVER 中通過存儲過程獲得自增的主鍵值

解決這樣的問題可以有兩種方法,筆者在這裏歸爲:預知法和後知法

預知法

預知法,其實相對簡單一些,我們可以設置一個主鍵,但該主鍵不設置爲自增,因爲在插入前,我們自己通過程序的方法獲得一個唯一的值作爲我們的主鍵.這樣就避免了我們插入後不能獲得主鍵的缺點,並且由於我們是預知我們要插入的值,所以在插入後,我們就可以不通過數據庫提供的方法,再次獲得主鍵.

在這裏我推薦使用一種比較好的預知序列,這就是GUID.大家都知道任何兩臺計算機都不可能產生一樣的GUID值,並且在一臺機器上產生的GUID也不會重複.

我們在插入數據庫前,自己通過GUID函數獲得一個可用的GUID,然後用它做爲主鍵來插入到數據庫中.

但是這也有一個缺點:GUID一般都比較長16位,並且它不具有任何的含義,這樣在大批量插入時有一定的性能影響.

後知法

後知法是本次我介紹的比較實用的方法,通過SQL Server的兩個函數和一個系統變量獲得當前最新的主鍵值

兩個函數分別是:

IDENT_CURRENT

SCOPE_IDENTITY

系統變量值爲:

@@IDENTITY

其中IDENT_CURRENT和SCOPE_IDENTITY的主要區別在於,SCOPE_IDENTITY主要用在一個會話中,只對當前會話插入的表的最後的IDENTITY,而IDENT_CURRENT沒有作用域的概念,它用於特定的表.

其中我主要介紹一下系統變量@@IDENTITY,以下是SQL Server在線幫助提供的信息

@@IDENTITY
  新增信息 - 2001 年 9 月

返回最後插入的標識值。

語法
@@IDENTITY

返回類型
numeric

註釋
在一條 INSERT、SELECT INTO 或大容量複製語句完成後,@@IDENTITY 中包含此語句產生的最後的標識值。若此語句沒有影響任何有標識列的表,則 @@IDENTITY 返回 NULL。若插入了多個行,則會產生多個標識值,@@IDENTITY 返回最後產生的標識值。如果此語句激發一個或多個執行產生標識值的插入操作的觸發器,則語句執行後立即調用 @@IDENTITY 將返回由觸發器產生的最後的標識值。如果觸發器在具有標識列的表上執行插入操作後激發,並且觸發器插入到另一個沒有標識列的表中,則 @@IDENTITY 將返回第一個插入的標識值。若 INSERT 或 SELECT INTO 語句失敗或大容量複製失敗,或事務被回滾,則 @@IDENTITY 值不會還原爲以前的設置。

在返回插入到表的 @@IDENTITY 列的最後一個值方面,@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 函數類似。

@@IDENTITY 和 SCOPE_IDENTITY 將返回在當前會話的所有表中生成的最後一個標識值。但是,SCOPE_IDENTITY 只在當前作用域內返回值,而 @@IDENTITY 不限於特定的作用域。

IDENT_CURRENT 不受作用域和會話的限制,而受限於指定的表。IDENT_CURRENT 返回任何會話和任何作用域中爲特定表生成的標識值。有關更多信息,請參見 IDENT_CURRENT。

@@IDENTITY 函數的作用域是執行該函數的本地服務器。此函數不能應用於遠程或鏈接服務器。要獲得其他服務器上的標識值,請在遠程服務器或鏈接服務器上執行存儲過程,並使該存儲過程(在遠程或鏈接服務器的環境中執行)收集標識值並將其返回本地服務器上的調用連接。

示例
下面的示例向帶有標識列的表中插入一行,並用 @@IDENTITY 顯示在新行中使用的標識值。

INSERT INTO jobs (job_desc,min_lvl,max_lvl)
VALUES ('Accountant',12,125)
SELECT @@IDENTITY AS 'Identity'

具體實現的方法是,寫一個存儲過程,並且在插入完成以後,返回@@IDENTITY,以下是一個存儲過程的例子:

下列示例將創建兩個表 TZ 和 TY,並在 TZ 上創建一個 INSERT 觸發器。當將某行插入表 TZ 中時,觸發器 (Ztrig) 將激發並在 TY 中插入一行。

USE tempdb
GO
CREATE TABLE TZ (
   Z_id  int IDENTITY(1,1)PRIMARY KEY,
   Z_name varchar(20) NOT NULL)

INSERT TZ
   VALUES ('Lisa')
INSERT TZ
   VALUES ('Mike')
INSERT TZ
   VALUES ('Carla')

SELECT * FROM TZ

--Result set: This is how table TZ looks
Z_id   Z_name
-------------
1      Lisa
2      Mike
3      Carla

CREATE TABLE TY (
   Y_id  int IDENTITY(100,5)PRIMARY KEY,
   Y_name varchar(20) NULL)

INSERT TY (Y_name)
   VALUES ('boathouse')
INSERT TY (Y_name)
   VALUES ('rocks')
INSERT TY (Y_name)
   VALUES ('elevator')

SELECT * FROM TY
--Result set: This is how TY looks:
Y_id  Y_name
---------------
100   boathouse
105   rocks
110   elevator

/*Create the trigger that inserts a row in table TY
when a row is inserted in table TZ*/
CREATE TRIGGER Ztrig
ON TZ
FOR INSERT AS
   BEGIN
   INSERT TY VALUES ('')
   END

/*FIRE the trigger and find out what identity values you get
with the @@IDENTITY and SCOPE_IDENTITY functions*/
INSERT TZ VALUES ('Rosalie')

SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]
GO
SELECT   @@IDENTITY AS [@@IDENTITY]
GO

--Here is the result set.
SCOPE_IDENTITY
4
/*SCOPE_IDENTITY returned the last identity value in the same scope, which was the insert on table TZ*/

@@IDENTITY
115
/*@@IDENTITY returned the last identity value inserted to TY by the trigger, which fired due to an earlier


值得注意的是SCOPE_IDENTITY返回的本過程中影響的表TZ,而觸法器影響的TY表不被反映,而@@IDENTITY則反映當前所有影響的表,即包含觸發器影響的TY表

在使用過程中我們可以使用RETURN @@identity返回一個存儲過程獲得的值,然後在程序中獲得這個值,這樣就能獲得當前插入後生成的主鍵.
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章