Sql server WHERE子句未按逻辑顺序进行筛选
我正在编写一个通用搜索存储过程,以基于用户可以在UI中选择的许多过滤器在表中进行搜索(使用MS-SQL 2008) 以下是简化版本:Sql server WHERE子句未按逻辑顺序进行筛选,sql-server,sql-server-2008,tsql,isnull,Sql Server,Sql Server 2008,Tsql,Isnull,我正在编写一个通用搜索存储过程,以基于用户可以在UI中选择的许多过滤器在表中进行搜索(使用MS-SQL 2008) 以下是简化版本: CREATE PROCEDURE SearchAll @FirstName NVARCHAR(MAX) = NULL, @LastName NVARCHAR(MAX) = NULL, @Age INT = NULL AS SELECT * FROM persons WHERE (@FirstNa
CREATE PROCEDURE SearchAll
@FirstName NVARCHAR(MAX) = NULL,
@LastName NVARCHAR(MAX) = NULL,
@Age INT = NULL
AS
SELECT *
FROM persons
WHERE
(@FirstName IS NULL OR FirstName = @firstname)
AND (@LastName IS NULL OR LastName = @LastName)
AND (@Age IS NULL OR Age = @Age)
似乎如果我将NULL传递给@Age,就不会有性能成本。但是,当我使用大量数据进行测试时,我会损失大量性能
以下是逻辑上相同但实际情况却大不相同的查询:
DECLARE @FirstName NVARCHAR(MAX) = NULL
DECLARE @Age INT = 23
------------First slow------------
SELECT *
FROM persons
WHERE
(@FirstName IS NULL OR FirstName = @firstname)
AND (@Age IS NULL OR Age = @Age)
------------Very fast------------
SELECT *
FROM persons
WHERE
Age = @Age
有没有漏掉一点
我知道SQL引擎会找到索引的最佳匹配,而且。。。(在运行查询之前),但很明显:@FirstName为NULL
,不需要分析任何内容
我还测试了查询中的
ISNULL
函数(结果相同)。包含@变量为null或@variable=column
构造的查询会导致性能灾难。这是因为SQL计划是为变量的任何值创建的。对于该主题的详细讨论,问题和可能的解决方案请参见前面已经提到的问题是,将构建查询计划以处理变量的任何值。您可以通过仅使用所需参数构建查询来规避此问题,如下所示:
CREATE PROCEDURE SearchAll
@FirstName NVARCHAR(MAX) = NULL,
@LastName NVARCHAR(MAX) = NULL,
@Age INT = NULL
AS
BEGIN
DECLARE @sql NVARCHAR(MAX), @has_where BIT
SELECT @has_where = 0, @sql = 'SELECT * FROM persons '
IF @FirstName IS NOT NULL
SELECT @sql = @sql + 'WHERE FirstName = ''' + @FirstName + '''', @has_where = 1
IF @LastName IS NOT NULL
SELECT @sql = @sql + CASE WHEN @has_where = 0 THEN 'WHERE ' ELSE 'AND ' END + 'LastName = ''' + @LastName + '''', @has_where = 1
IF @Age IS NOT NULL
SELECT @sql = @sql + CASE WHEN @has_where = 0 THEN 'WHERE ' ELSE 'AND ' END + 'Age = ' + CAST(@Age AS VARCHAR), @has_where = 1
EXEC sp_executesql @sql
END
在WHERE子句中为我的变量使用“CASE-WHEN”如何?您的问题是访问路径,而不是运算符短路。这个案子毫无帮助。