我有一个程序,它返回ID与传递的参数相关联的行,即1,5,7,9
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 :(得分: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注入漏洞。
答案 1 :(得分: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
答案 2 :(得分:0)
您不能将逗号分隔的字符串与in
运算符一起使用,您必须使用实际值。因此,您要么必须拆分字符串并将值放在临时表中,要么将字符串连接到查询中:
set @query = 'SELECT name FROM user WHERE id IN (' + @p_MyCodes + ')'
请注意,这为SQL注入打开了一个潜在的安全漏洞。如果您无法完全控制字符串的来源,则不应该这样做。