58

假设我得到以下信息:

DECLARE @ExcludedList VARCHAR(MAX)

SET @ExcludedList = 3 + ', ' + 4 + ' ,' + '22'

SELECT * FROM A WHERE Id NOT IN (@ExcludedList)

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

我明白为什么会出现错误,但我不知道如何解决它......

4

8 回答 8

53

这是一个示例,我使用 table 变量在 IN 子句中列出多个值。显而易见的原因是能够在漫长的过程中仅将值列表更改一个位置。

为了使其更加动态和允许用户输入,我建议为输入声明一个 varchar 变量,然后使用 WHILE 循环遍历变量中的数据并将其插入到表变量中。

用真实的东西替换@your_list、Your_table 和值。

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 语句将执行相同的操作:

SELECT *  
FROM your_table 
WHERE your_column in ('value','value2376' )
于 2014-12-11T12:46:24.187 回答
45

您需要将其作为动态 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
于 2010-05-31T15:51:47.480 回答
20
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)

我知道我正在回复一篇旧帖子,但我想分享一个示例,说明如何在想要避免使用动态 SQL 时使用变量表。我不确定它是否是最有效的方法,但是在过去,当动态 SQL 不是一个选项时,这对我来说是有效的。

于 2011-10-18T19:59:18.933 回答
9

您不能在IN子句中使用变量 - 您需要使用动态 SQL,或使用函数(TSQL 或 CLR)将值列表转换为表

动态 SQL 示例:

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
于 2010-05-31T15:48:20.903 回答
6

首先,创建一个快速函数,它将分隔的值列表拆分为一个表,如下所示:

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,您希望选择所有值,但如果它有一个或多个值,您希望报表数据根据这些值进行过滤。然后像这样使用 SQL:

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

这样,如果 @ExcludeList 是 NULL 值,则连接中的 OR 子句将成为关闭对该值的过滤的开关。非常便利...

于 2014-08-29T17:22:19.377 回答
1

我认为问题出在

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)
于 2010-05-31T15:36:28.363 回答
1

试试这个:

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
于 2010-05-31T15:47:15.527 回答
1

我有另一种解决方案,无需动态查询。我们也可以在 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)

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

于 2011-12-21T20:13:21.687 回答