如何在Microsoft Transact SQL中根据参数值构建where子句
实现动态WHERE子句的两种主流方案
方案1:使用sp_executesql执行动态拼接SQL(你考虑的方向完全正确,是灵活度最高的实现方式)
核心原则是只拼接条件逻辑,所有可变值通过参数化传入,彻底避免SQL注入风险,具体实现步骤如下:
- 先声明基础SQL和参数定义
DECLARE @sql NVARCHAR(MAX) = N'SELECT 所需列 FROM 表名 WHERE 1=1' -- 加1=1是为了方便后续拼接所有AND条件,不用判断第一个条件要不要加AND DECLARE @param NVARCHAR(100) -- 替换为你实际的入参类型和长度 -- 定义参数列表,所有要传入动态SQL的参数都要在这里声明类型 DECLARE @paramDef NVARCHAR(MAX) = N'@param NVARCHAR(100)'
- 根据入参取值拼接对应WHERE条件
-- 场景1:参数对应单值精确匹配 IF @param = N'触发单值匹配的特定取值' SET @sql += N' AND field1 = @param' -- 场景2:参数对应IN多值查询 ELSE IF @param = N'触发IN查询的特定取值' -- 如果IN里的值是固定枚举,直接写就行 SET @sql += N' AND field1 IN (N''枚举值1'', N''枚举值2'', N''枚举值3'')' -- 如果IN里的值也是动态传入的,不要直接拼值,用参数化写法: -- 先给@paramDef加新参数定义:N'@param NVARCHAR(100), @inList NVARCHAR(MAX)' -- 然后拼接条件:SET @sql += N' AND field1 IN (SELECT value FROM STRING_SPLIT(@inList, '',''))' -- 场景3:参数对应IN加LIKE组合条件 ELSE IF @param = N'触发组合查询的特定取值' SET @sql += N' AND (field1 IN (N''枚举值A'', N''枚举值B'') OR field1 LIKE @param + N''%'')'
- 调用
sp_executesql执行语句
EXEC sp_executesql @stmt = @sql, @params = @paramDef, @param = @param -- 多个参数的话按定义顺序依次传入即可
注意:绝对不要把用户输入的内容直接拼到SQL字符串里,所有可变值都走参数化传入,就不会有SQL注入风险。
方案2:静态SQL写法(适合条件分支较少的场景,无需拼接SQL)
如果你的业务判断分支不多,也可以直接把逻辑写在WHERE子句里,不用动态拼接:
SELECT 所需列 FROM 表名 WHERE ( @param = N'触发单值匹配的取值' AND field1 = @param ) OR ( @param = N'触发IN查询的取值' AND field1 IN (N'枚举值1', N'枚举值2', N'枚举值3') ) OR ( @param = N'触发组合查询的取值' AND (field1 IN (N'枚举值A', N'枚举值B') OR field1 LIKE @param + '%') )
该方案的缺点是分支较多时,SQL生成的执行计划可能不是最优,性能会比针对性拼接的动态SQL差。
内容的提问来源于stack exchange,提问作者Steve Cross
相关产品推荐
相关产品推荐

