现代的 BI 和 CRM 系统通常要求实现用户自定义过滤器:重要的是灵活组合任意条件(按日期、性别、状态、标签),以及在 SQL 语言中正确交叉和组合它们。生成的代码应当易于阅读、易于修改,并能产生预期的结果。
开发者经常“即时”生成包含多个 AND/OR 的 WHERE 语句,这会导致逻辑错误和难以维护的查询。如果过滤器的值可能缺失或与 IN/EXISTS/LIKE 组合使用,问题会进一步加剧。
对于动态过滤器,可使用“如果值未指定,则 OR 条件始终为 TRUE”模式:
SELECT * FROM users WHERE (status = @status OR @status IS NULL) AND (gender = @gender OR @gender IS NULL) AND (created >= @from_date OR @from_date IS NULL) AND (city IN (@cities) OR @cities IS NULL);
或者使用动态 SQL:
DECLARE @sql NVARCHAR(MAX) = N'SELECT * FROM users WHERE 1=1'; IF @status IS NOT NULL SET @sql += N' AND status = @status'; IF @gender IS NOT NULL SET @sql += N' AND gender = @gender'; -- ... EXEC sp_executesql @sql, N'@status NVARCHAR(10),@gender NVARCHAR(10)', @status, @gender;
关键特性:
可以在各处使用 WHERE 1=1 而不是检查条件的存在吗?
不可以,1=1 仅仅是用于连接 WHERE 的起始条件——它并不替代过滤器,而是仅用于方便生成查询。
如果 IN () 中包含空列表,会出现什么问题?
IN (NULL) 或 IN () 始终返回 false,并生成空结果集,即使没有过滤器。为了确保正确工作,应单独检查列表是否为空,并根本不包括该条件。
这样的结构如何影响索引使用和性能?
如果过滤器使用 OR 或 NULL 检查,许多数据库管理系统将无法有效使用索引,或者将执行整个表的扫描。建议使用动态 SQL 或参数化查询的过滤方法,以便优化器能够选择索引。
经典报告包含 10 个过滤器,代码形成包含多个 OR 的 WHERE——当多个过滤器缺失时,结果返回空集或过大的扫描,服务器负担增加数倍
优点:
单独的函数仅根据提供的参数生成过滤器,且每组条件仅启用单独的 JOIN/FILTER。Where 不包含 OR 和多余的 NULL 检查。
优点: