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

将逗号分隔字符串作为参数传入IN子句能否防范SQL注入?

这个IN子句用字符串参数的存储过程能防SQL注入吗?

先给结论:

  • 防注入是能防,但这个写法逻辑完全错误,根本达不到你想要的多值筛选效果。

为什么逻辑错误?

当你把'1,3'这种逗号分隔的字符串传入@StatusCodes参数时,SQL Server会把整个字符串当成单一的搜索值,而不是拆成1和3两个值。也就是说,实际执行的是:

WHERE ActionStatusCode = '1,3'

而不是你期望的:

WHERE ActionStatusCode IN (1,3)

除非你的ActionStatusCode字段存的是类似'1,3'这样的字符串,否则这个存储过程查不出你要的结果。

关于SQL注入的安全性

这个写法用了参数化查询,所以不存在SQL注入风险。参数化查询会把@StatusCodes里的内容当成纯数据处理,不会解析其中的SQL语句。哪怕有人恶意传入'1'); DROP TABLE Action; --这种字符串,SQL Server也只会把它当作一个普通字符串去匹配ActionStatusCode字段,不会执行里面的DROP语句。


正确的实现方式

既然你想要便捷又安全的多值筛选,推荐两种常用方法:

1. 表值参数(推荐,高效且规范)

先创建一个自定义表类型:

CREATE TYPE StatusCodeList AS TABLE (StatusCode INT);

然后修改存储过程:

CREATE PROCEDURE CurrentActions   
    @StatusCodes StatusCodeList READONLY
AS   
    SELECT ActionId, ActionName, ActionStatusCode, Comments  
    FROM Action
    WHERE ActionStatusCode IN (SELECT StatusCode FROM @StatusCodes)
GO

调用时直接传入包含多个状态码的表参数,这种方式是SQL Server官方推荐的多值传递方案,安全且性能好。

2. 使用STRING_SPLIT拆分字符串(适合SQL Server 2016+)

如果无法使用表值参数,可以用内置的STRING_SPLIT函数拆分逗号分隔的字符串:

CREATE PROCEDURE CurrentActions   
    @StatusCodes nvarchar(100)
AS   
    SELECT ActionId, ActionName, ActionStatusCode, Comments  
    FROM Action
    WHERE ActionStatusCode IN (
        SELECT TRY_CAST(value AS INT) 
        FROM STRING_SPLIT(@StatusCodes, ',') 
        WHERE TRY_CAST(value AS INT) IS NOT NULL
    )
GO

这里用TRY_CAST是为了避免传入非数字字符串时报错,自动过滤无效值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:12:30