我更倾向于使用动态SQL结合参数化的方案。这种方法灵活性高,能根据实际条件动态构建查询,避免了大量OR条件导致的性能问题,同时参数化防止了SQL注入。示例代码如下:DECLARE @sql NVARCHAR(MAX), @where NVARCHAR(MAX) = ''; IF @param1 IS NOT NULL SET @where += ' AND col1 = @p1'; IF @param2 IS NOT NULL SET @where += ' AND col2 LIKE '%' + @p2 + '%'; SET @sql = 'SELECT * FROM table WHERE 1=1' + @where; EXEC sp_executesql @sql, N'@p1 INT, @p2 NVARCHAR(50)', @p1, @p2;
方案一:使用OR条件
最简单的方法就是用OR连接多个条件,比如 SELECT * FROM Users WHERE (@name IS NULL OR name LIKE '%'+@name+'%') AND (@age IS NULL OR age = @age)。优点是代码简单直观,缺点是条件多时查询计划可能不佳,性能差。
方案二:IF分支判断
用多个IF语句根据参数是否为空执行不同的查询。例如:IF @name IS NOT NULL AND @age IS NOT NULL BEGIN SELECT * FROM Users WHERE name=@name AND age=@age; END ELSE IF @name IS NOT NULL BEGIN SELECT * FROM Users WHERE name=@name; END。这种方式每个分支可以优化索引,但代码冗长,维护麻烦。
方案三:动态SQL
构建动态SQL字符串,只拼接有值的条件:DECLARE @sql varchar(8000); SET @sql = 'SELECT * FROM Users WHERE 1=1'; IF @name IS NOT NULL SET @sql = @sql + ' AND name LIKE ''%' + @name + '%'''; EXEC(@sql)。灵活,但需小心SQL注入,最好用sp_executesql参数化。
方案四:使用表值参数
创建用户定义表类型作为参数,传入多个条件值,然后用INNER JOIN或EXISTS匹配。这种适合复杂多条件,性能好,但前期开发成本高。
个人推荐
综合考虑,我倾向动态SQL + sp_executesql参数化。既灵活又安全,性能在条件不多时很不错。避免了硬编码OR和IF分支的缺点。
FAQ
Q: 动态SQL如何防止注入?
A: 使用sp_executesql并全部参数化,不要直接拼接用户输入。
Q: 多条件查询性能最差的是哪种?
A: 大量OR条件,因为优化器难以选择最佳计划。
Q: 什么时候用IF分支?
A: 条件组合固定且少时,分支不多的情况下。
Q: 表值参数适合什么场景?
A: 需要传集合条件,如批量ID查询。