SQL Server的 – 在声明variables的子句中

假设我有以下几点:

DECLARE @ExcludedList VARCHAR(MAX) SET @ExcludedList = 3 + ', ' + 4 + ' ,' + '22' SELECT * FROM A WHERE Id NOT IN (@ExcludedList) 

错误:将varchar值“,”转换为数据typesint时转换失败。

我明白为什么错误在那里,但我不知道如何解决它…

你需要像一个dynamic的sp执行这个

 DECLARE @ExcludedList VARCHAR(MAX) SET @ExcludedList = '3,4,22,6014' declare @sql nvarchar(Max) Set @sql='SELECT * FROM [A] WHERE Id NOT IN ('+@ExcludedList+')' exec sp_executesql @sql 

这是一个使用表variables在IN子句中列出多个值的示例。 显而易见的原因是能够在一个很长的过程中只改变一个值的列表。

为了使它更加dynamic,并允许用户input,我build议为input声明一个varcharvariables,然后使用WHILE循环variables中的数据并将其插入到表variables中。

将@your_list,Your_table和值replace成真正的东西。

 DECLARE @your_list TABLE (list varchar(25)) INSERT into @your_list VALUES ('value1'),('value2376') SELECT * FROM your_table WHERE your_column in ( select list from @your_list ) 

select语句abowe将执行相同的操作:

 SELECT * FROM your_table WHERE your_column in ('value','value2376' ) 
 DECLARE @IDQuery VARCHAR(MAX) SET @IDQuery = 'SELECT ID FROM SomeTable WHERE Condition=Something' DECLARE @ExcludedList TABLE(ID VARCHAR(MAX)) INSERT INTO @ExcludedList EXEC(@IDQuery) SELECT * FROM A WHERE Id NOT IN (@ExcludedList) 

我知道我正在回应一个旧的post,但我想分享一个如何使用variables表的例子,当一个人想避免使用dynamicSQL。 我不确定它是否是最有效的方法,但是当dynamicSQL不是一个选项时,这在过去对我来说是有效的。

首先,创build一个快速的函数,将一个分隔的值列表分割成一个表格,如下所示:

 CREATE FUNCTION dbo.udf_SplitVariable ( @List varchar(8000), @SplitOn varchar(5) = ',' ) RETURNS @RtnValue TABLE ( Id INT IDENTITY(1,1), Value VARCHAR(8000) ) AS BEGIN --Account for ticks SET @List = (REPLACE(@List, '''', '')) --Account for 'emptynull' IF LTRIM(RTRIM(@List)) = 'emptynull' BEGIN SET @List = '' END --Loop through all of the items in the string and add records for each item WHILE (CHARINDEX(@SplitOn,@List)>0) BEGIN INSERT INTO @RtnValue (value) SELECT Value = LTRIM(RTRIM(SUBSTRING(@List, 1, CHARINDEX(@SplitOn, @List)-1))) SET @List = SUBSTRING(@List, CHARINDEX(@SplitOn,@List) + LEN(@SplitOn), LEN(@List)) END INSERT INTO @RtnValue (Value) SELECT Value = LTRIM(RTRIM(@List)) RETURN END 

然后像这样调用函数…

 SELECT * FROM A LEFT OUTER JOIN udf_SplitVariable(@ExcludedList, ',') f ON A.Id = f.Value WHERE f.Id IS NULL 

这对我们的项目非常有效

当然,如果是这样的话,也可以做相反的事情(虽然不是你的问题)。

 SELECT * FROM A INNER JOIN udf_SplitVariable(@ExcludedList, ',') f ON A.Id = f.Value 

处理具有可选多选参数列表的报告时,这真的很方便。 如果参数为NULL,则需要select所有值,但是如果它具有一个或多个值,则需要根据这些值过滤报告数据。 然后像这样使用SQL:

 SELECT * FROM A INNER JOIN udf_SplitVariable(@ExcludedList, ',') f ON A.Id = f.Value OR @ExcludeList IS NULL 

这样,如果@ExcludeList是一个NULL值,则连接中的OR子句成为一个closures对该值的过滤的开关。 非常方便…

您不能在IN子句中使用variables – 您需要使用dynamicSQL ,或使用函数(TSQL或CLR)将值列表转换为表格 。

dynamicSQL示例:

 DECLARE @ExcludedList VARCHAR(MAX) SET @ExcludedList = 3 + ',' + 4 + ',' + '22' DECLARE @SQL NVARCHAR(4000) SET @SQL = 'SELECT * FROM A WHERE Id NOT IN (@ExcludedList) ' BEGIN EXEC sp_executesql @SQL '@ExcludedList VARCHAR(MAX)' @ExcludedList END 

我想问题在于

 3 + ', ' + 4 

改变它

 '3' + ', ' + '4' DECLARE @ExcludedList VARCHAR(MAX) SET @ExcludedList = '3' + ', ' + '4' + ' ,' + '22' SELECT * FROM A WHERE Id NOT IN (@ExcludedList) 

SET @ExcludedListe,使您的查询应该成为

 SELECT * FROM A WHERE Id NOT IN ('3', '4', '22') 

要么

 SELECT * FROM A WHERE Id NOT IN (3, 4, 22) 

尝试这个:

 CREATE PROCEDURE MyProc @excludedlist integer_list_tbltype READONLY AS SELECT * FROM A WHERE ID NOT IN (@excludedlist) 

然后像这样调用它:

 DECLARE @ExcludedList integer_list_tbltype INSERT @ExcludedList(n) VALUES(3, 4, 22) exec MyProc @ExcludedList 

我有另一个解决scheme,没有dynamic查询。 我们也可以在xquery的帮助下做到这一点。

  SET @Xml = cast(('<A>'+replace('3,4,22,6014',',' ,'</A><A>')+'</A>') AS XML) Select @Xml SELECT A.value('.', 'varchar(max)') as [Column] FROM @Xml.nodes('A') AS FN(A) 

这里是完整的解决scheme: http : //raresql.com/2011/12/21/how-to-use-multiple-values-for-in-clause-using-same-parameter-sql-server/