2009-10-22 424 views
0

我将逗号分隔的值列表传递给存储过程。我需要执行查询以查看实体的ID是否在逗号分隔列表中。不幸的是,我觉得我不明白。SQL Server - 替换单引号并使用IN

当我执行以下存储过程:

exec dbo.myStoredProcedure @myFilter=N'1, 2, 3, 4' 

我收到以下错误:

"Conversion failed when converting the varchar value '1, 2, 3, 4' to data type int." 

我的存储过程是非常基本的。它看起来像这样:

CREATE PROCEDURE [dbo].[myStoredProcedure] 
    @myFilter nvarchar(512) = NULL 
AS 
SET NOCOUNT ON 
BEGIN 
    -- Remove the quote marks so the filter will work with the "IN" statement 
    SELECT @myFilter = REPLACE(@myFilter, '''', '') 

    -- Execute the query 
    SELECT 
     t.ID, 
     t.Name  
    FROM 
     MyTable t 
    WHERE 
     t.ID IN (@myFilter) 
    ORDER BY 
     t.Name 
END 

如何在SQL语句中使用参数如上所述?谢谢!

+0

您是否搜索过somma分隔的参数? – 2009-10-22 20:34:37

回答

4

您可以制作带您的参数的函数,将其滑入并返回其中包含所有数字的表。

如果您是在SQL服务器列表或数组的工作,我建议您阅读厄兰Sommarskogs奇妙的东西:

Arrays and Lists in SQL Server 2005

3

您需要拆分字符串并将其转储到临时表中。然后你加入临时表。

有很多这样的例子,这里是一个随机的例子。

http://blogs.microsoft.co.il/blogs/itai/archive/2009/02/01/t-sql-split-function.aspx

+0

或者,您可以将逗号分隔列表转换为XML,并将XML作为参数传递给存储过程。你仍然会加入XML,但你至少应该避免编写一个分割函数。 – 2009-10-22 20:21:05

+0

@iKnowFungFoo:使用XML意味着用标记而不是内容吃掉字符 - 运行不能发送所有内容的风险 – 2009-10-22 20:32:03

+0

@iKnowKungFoo:在@rexem所说的之上,如果你有很多要发送的数据,标记也会变得太大,因此查询变慢。 – Sung 2009-10-22 20:36:29

0

我会创建一个函数,你的逗号分隔字符串,将其分解并返回单个列的表变量在其自己的行每一个值。从IN语句的返回表中选择该列。

0

我发现了一个可爱的做法 - 但它闻起来有点。

declare @delimitedlist varchar(8000) 
set @delimitedlist = '|1|2|33|11|3134|' 

select * from mytable where @delimitedlist like '%|' + cast(id as varchar) + '|%' 

所以......这将返回所有记录与一个id等于1,2,33,11,或3134

编辑: 我还想补充一点,这是不容易到SQL注入(而动态SQL依赖于您的白名单/黑名单技术来确保它不易被攻击)。它可能会对大量数据产生性能影响,但它可以工作并且很安全。

+1

我想你会阻止SQL使用索引查找并强制它扫描, – Andrew 2009-10-22 20:18:49

+0

cast varchar as ???至少应该定义多于一个单独的字符。 – 2009-10-22 20:19:06

+1

@Andrew:你是对的 - 它的表现很糟糕,因为它不能使用索引,因为在LIKE条件开始时使用了%。 – 2009-10-22 20:19:42

2

缺席的分裂功能,这样的事情:

CREATE PROCEDURE [dbo].[myStoredProcedure] 
    @myFilter varchar(512) = NULL -- don't use NVARCHAR for a list of INTs 
AS 
SET NOCOUNT ON 
BEGIN 
    SELECT 
     t.ID, 
     t.Name   
    FROM 
     MyTable t 
    WHERE 
     CHARINDEX(','+CONVERT(VARCHAR,t.ID)+',',@myFilter) > 0 
    ORDER BY 
     t.Name 
END 

性能会很差。每次扫描一次表格。最好使用分割功能。请参阅:http://www.sommarskog.se/arrays-in-sql.html