假设我得到以下信息:
DECLARE @ExcludedList VARCHAR(MAX)
SET @ExcludedList = 3 + ', ' + 4 + ' ,' + '22'
SELECT * FROM A WHERE Id NOT IN (@ExcludedList)
错误:将 varchar 值“,”转换为数据类型 int 时转换失败。
我明白为什么会出现错误,但我不知道如何解决它......
假设我得到以下信息:
DECLARE @ExcludedList VARCHAR(MAX)
SET @ExcludedList = 3 + ', ' + 4 + ' ,' + '22'
SELECT * FROM A WHERE Id NOT IN (@ExcludedList)
错误:将 varchar 值“,”转换为数据类型 int 时转换失败。
我明白为什么会出现错误,但我不知道如何解决它......
这是一个示例,我使用 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' )
您需要将其作为动态 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
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 不是一个选项时,这对我来说是有效的。
您不能在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
首先,创建一个快速函数,它将分隔的值列表拆分为一个表,如下所示:
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 子句将成为关闭对该值的过滤的开关。非常便利...
我认为问题出在
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
我有另一种解决方案,无需动态查询。我们也可以在 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)