存储过程中的SQL IN子句

我有一个传递以下数据的C#应用​​程序:

datasetID = 10; userID = 1; varnames =“’ACT97’,’ACTCHNG’,’ACTQTR2’,’ACTSCOR2’”;

存储过程是:

SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[s_LockCheck] -- Add the parameters for the stored procedure here @varNames VARCHAR(max), @datasetID INT, @userID INT AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON SELECT COUNT(*) as locked FROM VarLocks WHERE var_name IN (@varNames) AND dataset_id = @datasetID AND user_id != @userID AND is_locked = 1 END 

但是当我这样称它时,它应该高于0时返回0的计数:

 exec s_LockCheck "'ACT97','ACTCHNG','ACTQTR2','ACTSCOR2'", 88, 14 

上面的每个ACTXXX都是列var_name的varname。

为什么不正确地执行IN子句?

有几种方法可以实现此目的:

  1. 动态SQL,如本文所述: http : //asheej.blogspot.com/2012/04/how-to-use-ms-sql-in-clause-with.html

  2. 在变量中指定每个项目(如果你有很多的话,这可能会非常难看):

    @ var1 varchar(20),@ var2 varchar(20),@ var3 varchar(20)

  3. 编写一个split函数将字符串转换为表变量,其中有很多。 这个是我个人的最爱: http : //sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx

  4. 使用表值参数(2008): http : //www.techrepublic.com/blog/datacenter/passing-table-valued-parameters-in-sql-server-2008/168

  5. 这是使用CHARINDEX的一个小技巧(注意这种方法是非Sargable):

你的字符串是这样的:’abc,def’

使用CHARINDEX ,您可以使用分隔符填充搜索字符串和要在搜索字符串中查找的值。 因此,使用我的小例子,字符串将变为’,abc,def,’注意开头和结尾的额外逗号。 然后对字段数据执行相同的操作。 如果您的数据中有逗号,则必须将分隔符换成其他内容,例如char(2)或分号或其他内容。

然后执行搜索:

 WHERE CHARINDEX ( ',' + expressionToFind + ',' , ',' + expressionToSearch ',') > 0 

分隔符填充使搜索无法找到“abcabc”,但会找到“abc”,完全匹配。

如果您使用的是2005,我会抓住一个非常快速的分割函数,这样您就可以避免使用动态SQL。