Ⅰ 如何在sql server中准確的獲得標識值
轉:
SQL Server有三種不同的函數可以用來獲得含有標識列的表裡最後生成的標識值:
@@IDENTITY
SCOPE_IDENTITY()
IDENT_CURRENT('數據表名')
以上三個函數雖然都可以返回資料庫引擎最後生成插入標識列的值,但是根據插入行的來源(例如:存儲過程或觸發器)以及插入該行的連接不同,這三個函數在功能上也有所不同。
@@IDENTITY函數可以返回所有范圍內當前連接插入最後所生成的標識值(包括任何調用的存儲過程和觸發器)。這個函數不止可以適用於表。函數返回的值是最後表插入行生成的標識值。
SCOPE_IDENTITY()函數跟上一個函數幾乎是一摸一樣的,不同的地方:即前者返回的值只限於當前范圍(即執行中的存儲過程)。
最後是IDENT_CURRENT函數,它可以用於所有范圍和所有連接,獲得最後生成的表標識值。跟前面兩個函數不同的是,這個函數只用於表,並且使用[數據表名]作為一個參數。
我們可以舉實例來演示上述函數是如何運作的。
首先,我們創建兩個簡單的例表:一個代表客戶表,一個代表審計表。創建審計表的目的是為了跟蹤資料庫里插入和刪除信息的所有記錄。
以下是引用片段:
CREATE TABLE dbo.customer
(customerid INT IDENTITY(1,1) PRIMARY KEY)
GO
CREATE TABLE dbo.auditlog
(auditlogid INT IDENTITY(1,1) PRIMARY KEY,
customerid INT, action CHAR(1),
changedate datetime DEFAULT GETDATE())
GO
然後,我們還要創建一個存儲過程和一個輔助觸發器,這個存儲過程將在資料庫表裡插入新的客戶行,並返回生成的標識值,而觸發器則會向審計表插入行:
以下是引用片段:
CREATE PROCEDURE dbo.p_InsertCustomer @customerid INT output
AS
SET nocount ON
INSERT INTO dbo.customer DEFAULT VALUES
SELECT @customerid = @@identity
GO
CREATE TRIGGER dbo.tr_customer_log ON dbo.customer
FOR INSERT, DELETE
AS
IF EXISTS (SELECT 'x' FROM inserted)
INSERT INTO dbo.auditlog (customerid, action)
SELECT customerid, 'I'
FROM inserted
ELSE
IF EXISTS (SELECT 'x' FROM deleted)
INSERT INTO dbo.auditlog (customerid, action)
SELECT customerid, 'D'
FROM deleted
GO
現在我們可以執行程序,創建客戶表的第一行了:
以下是引用片段:
DECLARE @customerid INT
EXEC dbo.p_InsertCustomer @customerid output
SELECT @customerid AS customerid
執行後返回了我們需要的第一個客戶的值,並記錄了插入審計表的條目。到目前為止,數據顯示沒有任何問題。
假設由於先前溝通出現了偏差,一個客戶服務代表現在需要從資料庫里刪除掉這個新增的客戶。我們現在就來把新插入的客戶行刪除掉:
以下是引用片段:
DELETE FROM dbo.customer WHERE customerid = 1
現在,客戶工作表為空表,而審計工作表裡則有兩行——第一行是記錄第一次插入行,第二行是記錄刪除客戶記錄。
現在我們再往資料庫里增加第二個客戶信息並檢測一下獲得的標識值:
以下是引用片段:
DECLARE @customerid INT
EXEC dbo.p_InsertCustomer @customerid output
SELECT @customerid AS customerid
哇!看看出現了什麼情況!如果我們現在再看客戶工作表,就會發現雖然創建了客戶2,但是我們的程序返回的標識值為3!到底出了什麼問題呢?回想一下,前面講過@@IDENTITY函數的作用范圍,它會返回主程序調用的任何存儲過程或觸動任何觸發器最後生成的標識值,取決於哪一個在函數被調用前最後生成標識值。在我們的例子里,初始范圍是p_InsertCustomer,然後是觸發器用來記錄插入條目的tr_customer_log。因此我們返回獲得的標識值是審計工作表裡觸發器插入生成的標識值,而不是我們想要的客戶工作表裡的生成的標識值。
在SQL Server 2000之前的版本,@@IDENTITY函數是獲得標識值的唯一方法。由於會出現這樣的存儲過程/觸發器問題,SQL Server開發團隊在SQL Server 2000中引入了 SCOPE_IDENTITY()和IDENT_CURRENT這兩個函數來解決這個問題。所以在舊的SQL Server版本里,要解決這個問題比較麻煩。如果是SQL Server6.5版本,我建議可以去掉標識列,然後創建一個可以包含下一個需要使用的值的輔助表,可以達到標識列的作用效果。不過這個辦法也不是什麼高明的辦法。
現在我們來修改一下存儲過程來使用SCOPE_IDENTITY()函數,並重新執行程序來添加第三個客戶條目:
以下是引用片段:
ALTER PROCEDURE dbo.p_InsertCustomer @customerid INT output
AS
SET nocount ON
INSERT INTO dbo.customer DEFAULT VALUES
SELECT @customerid = SCOPE_IDENTITY()
GO
DECLARE @customerid INT
EXEC dbo.p_InsertCustomer @customerid output
SELECT @customerid AS customerid
我們返回的標識值還是3,不過這次我們獲得的標識值是正確的,因為我們添加了第三個客戶條目。如果我們檢查一下審計工作表,就會發現裡面已經有第四個條目記錄新插入的客戶記錄。由於函數SCOPE_IDENTITY()只作用於當前范圍,只返回當前執行程序的值,這樣就避免了發生剛才那樣的問題。
前面講過,函數@@IDENTITY和函數SCOPE_IDENTITY()不止用於表,不像函數IDENT_CURRENT那樣可以用表作為參數。使用@@IDENTITY和SCOPE_IDENTITY()這兩個函數的話在設置代碼時需要加倍小心,才能夠從所需要的表裡獲得正確的標識值。從表面上來看,放棄這兩個函數,只使用函數IDENT_CURRENT並指定表是更安全的辦法。這樣可以避免出現獲得錯誤標識值的情況,對吧?記得先前說過函數IDENT_CURRENT不僅會跨范圍,而且它還會跨連接。也就是說,使用這個函數生成的值不僅僅限於你的連接所執行的程序,它的涵蓋范圍還包括整個資料庫所有的連接。因此,即使是在規模較小的OLTP環境里,它也會出現不能准確返回所需值的問題。這樣就可能發生類似前面@@IDENTITY函數/觸發器的數據損壞問題。
我的建議是函數SCOPE_IDENTITY()是三個函數里最安全的函數,應該設置為默認函數。使用這個函數,你可以放心地添加觸發器和次存儲過程,無需擔心意外損壞數據。而另外兩個函數可以保留應付特殊的情況,當遇到需要使用這兩個函數的特殊情況時,建議記錄它們的使用情況並進行測試。
小技巧:
Sql Server 判斷表是存在標識列
If Exists(Select * from SysColumns Where ID=OBJECT_ID(N'TEST1') And COLUMNPROPERTY(ID,Name,'IsIdentity')=1)
Print N'有自增列'
Else
Print N'沒有自增列'
Sql Server 顯示當前資料庫包含自增列的表
Select b.name,a.* from SysColumns a,sysobjects b Where a.id=b.id and COLUMNPROPERTY(a.ID,a.Name,'IsIdentity')=1
Ⅱ 如何獲取SQL資料庫標識信息(標識種子,遞增量)
@@IDENTITY 表示插入後新的表示種子值,例子如下:
假如已經存在表job,向表插入一條數據,
INSERT INTO jobs (job_desc,min_lvl,max_lvl)
VALUES ('Accountant',12,125)
SELECT @@IDENTITY AS 'Identity'//獲得表識值
Ⅲ SQL Server中怎麼獲取剛插入的標識值
返回最後插入的標識值的系統函數。
IDENT_CURRENT 類似於 SQL Server 2000 標識函數 SCOPE_IDENTITY 和
@@IDENTITY。這三個函數都返回最後生成的標識值。但是,上述每個函數中定義的「最後」的作用域和會話有所不同。
IDENT_CURRENT 返回為某個會話和用域中的指定表生成的最新標識值。
@@IDENTITY 返回為跨所有作用域的當前會話中的某個表生成的最新標識值。
SCOPE_IDENTITY 返回為當前會話和當前作用域中的某個表生成的最新標識值。
Ⅳ 如何用T_SQL語言來獲取最後一次的標識值
select @@identity 是全局標識,執行語句可以使用當前標識,select scope_Identity()
Ⅳ 關於SQL server 2005中的標識問題
創建表時指定自動編號的欄位
1.CREATE TABLE [dbo].[UserInfor]( [UserID] [int] IDENTITY(100,2) NOT NULL, [UserName] [nchar](10) NOT NULL, ) 說明:創建一個用戶信息表UserInfor,並指定UserID為自動編號欄位。
其中:IDENTITY(100,2)表示欄位的初始值為100,每次增量為2,如輸入數據後第一次為100,第二次為102。
2.獲取自動編號的欄位值
這里可以使用@@IDENTITY取得自動增加欄位主鍵的值
Ⅵ 各位SQL高手,先問個好! 需求:sql server 2008中獲取視圖唯一標識別欄位!
樓主在主鍵這個容易混人的問題上,沒有跳過這個砍
跳過來就太簡單了。
主鍵,也就是樓主說的唯一標識。
根據不同的情況主鍵也是不同的。
如:
實體類的表:
商品表(商品編號,商品名稱,出產日期。。。。)
他的主鍵肯定是「商品編號」,這個樓主也沒問題。
記錄類的表,通常是多個欄位的:
銷售記錄表(商品編號,銷售時間,銷售類型[售|退],營業員。。。。)
那麼「商品編號」「銷售時間」成為這個表的主鍵了
象樓主這種視圖叫關系表:
假設該視圖里:表1 有外鍵UserID,是表2的主鍵,OK
那麼主鍵肯定是第一張表的(id)和第二張表的(UserID)
對了,理解的很對!祝你快樂
Ⅶ 關於SQL SERVER裡面獲取自增列的標識值的問題
你的意思是獲取某個表中最後擦汗如的id值吧,這樣看看:
假定表明為temp,id列為ID
SELECT MAX(ID) FROM TEMP
因為自增列剛插入的ID肯定是最大的
Ⅷ 怎麼獲得jsp中的sql語句的標識列
SELECT * from SHOPPINGBUY_PRODUCT where id in (SELECT @@Identity FROM SHOPPINGBUY_PRODUCT);
id是我猜測的 你的肯定不叫ID 你的自增序列叫啥 你就寫啥就行了