2010-07-21 53 views
0

我有程序返回通過與傳遞的參數ID相關聯的行,即1,5,7,9T-SQL的一個問題,當通過CSV串入一個存儲過程

ALTER PROCEDURE [dbo].[get_data] 
@MyCodes as varchar(max) = '' 
AS 
BEGIN 
DECLARE @query as nvarchar(max) 

set @query = 'SELECT name FROM user WHERE id IN (@p_MyCodes)' 

exec SP_EXECUTESQL @query, 
         N'@p_MyCodes varchar(max)', 
         @p_MyCodes = @MyCodes 
END 

該程序生成一個錯誤:將數據類型varchar轉換爲數字時出錯。當我作爲一個參數傳遞例如3,7,5

怎麼了?

+0

檢出:http://www.adathedev.co.uk/2010/02/sql-server-2008-table-valued-parameters.html – AdaTheDev 2010-07-21 12:41:11

回答

3

我不認爲這會達到你期待的目標。你得到的錯誤是因爲它不能將字符串'3,7,5'轉換爲數字(注意它不是試圖解析出你的個人價值)。

兩種方式來獲得你想要的東西:

1)創建一個表值函數,接受CSV字符串,並返回結果(我敢肯定有很多在網絡上,這裏有一個相關的問題:Split function equivalent in T-SQL? )。這很好,因爲您可以完全擺脫SP_EXECUTESQL sproc調用;您的查詢就會變成:

SELECT name FROM user where id IN (SELECT value FROM dbo.f_Split(@p_MyCodes)) 

2)你的設置更改爲類似:

set @query = 'SELECT name FROM user WHERE id in (' + @p_MyCodes + ')' 

我不建議#2,它提供了一個SQL注入漏洞。

+0

我使用了第二個選項,但後來我需要更改' exec'clausule into:exec SP_EXECUTESQL @query,N'@ p_MyCodes nvarchar(max)',''然後所有的東西都可以正常工作:) – Tony 2010-07-21 13:01:35

1

您無法將ID列表作爲參數傳遞。您可以通過連接創建的SQL語句:

set @query = 'SELECT name FROM user WHERE id IN (' + @MyCodes + ')' 
exec SP_EXECUTESQL @query 

雖然,這將禁用任何類型的執行計劃重新使用的,使SQL注入

一個更好的解決辦法是將列表分割成一個臨時表(或表變量)並使用JOIN。去年,我寫了一篇博客文章不同的方式在T-SQL分割字符串: http://florianreischl.blogspot.com/2009/09/high-performance-string-split-functions.html

0

不能使用逗號分隔字符串的in運營商,你必須使用的實際值。所以,你要麼必須向上分割字符串,並把該值在一個臨時表,或將字符串到查詢:

set @query = 'SELECT name FROM user WHERE id IN (' + @p_MyCodes + ')' 

注意,這開闢了SQL注入潛在的安全漏洞。如果您不完全控制字符串的來源,則不應該這樣做。

相關問題