You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SQL Server中将列表作为变量传入WHERE IN子句

嘿,这个问题我天天见!你之所以用变量后返回空集,核心原因是SQL Server把你的@keys和@values当成了单个完整的字符串,而不是逗号分隔的多个独立值——打个比方,它会去匹配[key] = 'material, type',而不是分别匹配material和type,自然找不到结果啦。

下面给你几种靠谱的解决方案,按推荐度从高到低排序:

1. 使用STRING_SPLIT函数(SQL Server 2016及以上版本)

这是官方推荐的最简洁方案,STRING_SPLIT可以直接把CSV字符串拆分成一张包含单个值的临时表,完美适配IN子句。注意要加上TRIM处理掉逗号前后的空格(比如你示例里general purpose前面的空格):

DECLARE @keys NVARCHAR(MAX) = 'material, type'
DECLARE @values NVARCHAR(MAX) = 'nylon/latex, general purpose'

SELECT * 
FROM items 
WHERE [key] IN (SELECT TRIM(value) FROM STRING_SPLIT(@keys, ','))
  AND value IN (SELECT TRIM(value) FROM STRING_SPLIT(@values, ','))

2. 自定义字符串拆分函数(适用于SQL Server 2016之前的版本)

如果你的SQL Server版本比较老,没有STRING_SPLIT,可以自己写一个轻量的拆分函数:

CREATE FUNCTION dbo.SplitString
(
    @InputString NVARCHAR(MAX),
    @Delimiter NVARCHAR(5)
)
RETURNS @OutputTable TABLE (Value NVARCHAR(MAX))
AS
BEGIN
    DECLARE @StartIndex INT, @EndIndex INT

    SET @StartIndex = 1
    -- 确保字符串末尾有分隔符,避免漏拆最后一个值
    IF SUBSTRING(@InputString, LEN(@InputString), 1) <> @Delimiter
    BEGIN
        SET @InputString = @InputString + @Delimiter
    END

    WHILE CHARINDEX(@Delimiter, @InputString) > 0
    BEGIN
        SET @EndIndex = CHARINDEX(@Delimiter, @InputString)
        INSERT INTO @OutputTable(Value)
        SELECT TRIM(SUBSTRING(@InputString, @StartIndex, @EndIndex - @StartIndex))
        SET @InputString = SUBSTRING(@InputString, @EndIndex + 1, LEN(@InputString))
    END

    RETURN
END

使用方式和STRING_SPLIT类似:

DECLARE @keys NVARCHAR(MAX) = 'material, type'
DECLARE @values NVARCHAR(MAX) = 'nylon/latex, general purpose'

SELECT * 
FROM items 
WHERE [key] IN (SELECT Value FROM dbo.SplitString(@keys, ','))
  AND value IN (SELECT Value FROM dbo.SplitString(@values, ','))

3. 动态SQL(谨慎使用,注意SQL注入风险)

如果前两种方法都不适用,也可以用动态SQL拼接成原始的查询语句,但一定要注意SQL注入风险,如果参数来自用户输入,必须严格处理:

DECLARE @keys NVARCHAR(MAX) = 'material, type'
DECLARE @values NVARCHAR(MAX) = 'nylon/latex, general purpose'
DECLARE @sql NVARCHAR(MAX)

-- 转义字符串中的单引号,避免语法错误和注入
SET @keys = REPLACE(@keys, '''', '''''')
SET @values = REPLACE(@values, '''', '''''')

-- 拼接成原始的IN子句格式
SET @sql = 'SELECT * FROM items WHERE [key] IN (''' + REPLACE(@keys, ',', ''',''') + ''') AND value IN (''' + REPLACE(@values, ',', ''',''') + ''')'

EXEC sp_executesql @sql

⚠️ 注意:如果@keys或@values是用户可控的输入,这种方法存在注入风险,优先推荐前两种方案。

总的来说,如果你用的是SQL Server 2016及以后,直接用STRING_SPLIT是最简洁安全的;老版本就用自定义拆分函数;动态SQL尽量少用,除非万不得已,而且一定要做好安全校验。

内容的提问来源于stack exchange,提问作者ang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:35:38