2011-04-19 45 views
4

在存儲過程中,我使用INSERT動態創建查詢。這是爲了強制默認值(如果它是NULL,則使用@name)。從動態INSERT獲取IDENTITY

SET @sql = 'INSERT INTO table (username, password' 
    + CASE @name IS NULL THEN '' ELSE ',name' END 
    + ') VALUES (''root'',''gelehallon''' + 
    + CASE @name IS NULL THEN '' ELSE ',''@name''' END 
    + ')' 
EXEC sp_executesql @sql 

SET @id = SCOPE_IDENTITY() 

@id無論如何都是0。
即使另一個線程同時運行相同的存儲過程,如何以安全方式檢索IDENTITY?

+0

爲什麼你動態創建一個存儲過程的查詢? – 2011-04-19 08:09:42

+0

這是一種強制未傳遞到存儲過程的字段上的默認值的方法。假設我可能需要@name,但是如果不通過,它應該默認爲表格的默認值。因此,我動態構建它,如果沒有傳遞,則刪除@name。 – ANisus 2011-04-19 08:12:44

回答

10
SET @sql = 'INSERT INTO table (username, password) VALUES (@username,@pwd) 
    SELECT @id = SCOPE_IDENTITY()' 
EXEC sp_executesql @sql, 
    N'@username VARCHAR(50), @pwd VARCHAR(50), @id INTEGER OUTPUT', 
    'root', 'gelehallon', @id OUTPUT 

-- @id now has SCOPE_IDENTITY() value in 

雖然幾點:
- 假設這是因爲似乎沒有成爲一個需要使用動態SQL在這個例子中
一個簡單的例子 - 假設你不打算用來存儲實時密碼在純文本中的數據庫!

+0

*笑*不,這是一個簡化的例子,不,我正在使用salt和Sha1進行加密。別擔心。但謝謝你的答案! – ANisus 2011-04-19 08:18:22

+0

SHA1不再被視爲安全。 SHA-2在SQL Server 2012及更高版本中,或者您可以使用一些更加安全的方式(例如bcrypt),並付出一些額外的努力。 – reedstonefood 2016-03-22 12:33:31

1

或者,您可以使用帶有INSERT語句的OUTPUT子句。這將導致動態語句,並因此用於調用它的系統存儲過程返回一個行集(在你的情況下是一行)。您可以抓住機會並將行集插入到表變量中,然後讀取該值。

基本上,它可能是這樣的:

SET @sql = 'INSERT INTO table (...) OUTPUT inserted.ID VALUES (...)'; 
DECLARE @ScopeIdentity (ID int); 
INSERT INTO @ScopeIdentity 
    EXEC sp_executesql @sql; 
SELECT @id = ID FROM @ScopeIdentity;