我有一个名为Employee的表。 字段是
1.EmployeeId, 2.Name, 3.Salary, 4.Address
我需要编写一个程序来获取所有员工的详细信息。此过程的where子句是动态的。我能够编写动态查询来获取详细信息。但我最近探索了以下格式查询。
SELECT * FROM Employee
WHERE 1=1
AND EmployeeId = CASE WHEN @EmployeeId IS NULL OR LEN(@EmployeeId) =0 THEN EmployeeId ELSE @EmployeeId END
AND Name = CASE WHEN @Name IS NULL OR LEN(@Name) =0 THEN Name ELSE @Name END
...
...
ORDER BY Name ASC
@EmployeeId,@ name来自应用程序
可以告诉我这会对动态查询产生任何性能影响吗?或哪一个表现更好?
where子句条件是动态的。这对2条件并不严格。有时是1或3或4或0
对于任何拼写错误
抱歉提前致谢。
答案 0 :(得分:0)
让我们说这是您正在使用的数据:
-- sample data
USE tempdb;
GO
CREATE TABLE dbo.employee (EmployeeId int, Name varchar(100));
INSERT dbo.employee
SELECT TOP (100)
ABS(checksum(newid())%10)+1,
CASE abs(checksum(newid())%3)+1 WHEN 1 THEN 'Peter' WHEN 2 THEN 'Paul' ELSE 'Mary' END
+ ' ' +
CASE abs(checksum(newid())%3)+1 WHEN 1 THEN 'Smith' WHEN 2 THEN 'Jones' ELSE 'White' END
FROM sys.all_columns;
-- A good covering index
CREATE NONCLUSTERED INDEX nc_employee ON dbo.employee (EmployeeId, Name);
首先请注意,您可以使用此查询获得完全相同的结果和执行计划:
SELECT *
FROM dbo.employee
WHERE (EmployeeId = @EmployeeId OR NULLIF(LEN(@EmployeeId),0) IS NULL)
AND (Name = @Name OR NULLIF(LEN(@Name),0) IS NULL)
假设存在可用的索引 - 您的查询(或上面的查询)将创建一个基本的执行计划,包括索引搜索或索引扫描,以及SELECT运算符。扫描是否按原样运行查询,如果在任一查询结束时包含OPTION(RECOMPILE),则搜索...索引搜索比扫描要好得多。
使用上述OPTION(RECOMPILE)提示获取索引查找的另一种方法是使用动态SQL,如下所示。
DECLARE @EmployeeId int = 5,
@Name varchar(100) = 'Peter White';
DECLARE @sql nvarchar(2000) = N'SELECT * FROM dbo.employee';
DECLARE @ParmDefinition nvarchar(500);
SET @ParmDefinition = N'@EmployeeId int, @Name varchar(100)';
SET @sql +=
CASE
WHEN (NULLIF(LEN(@EmployeeId),0) IS NOT NULL AND NULLIF(LEN(@Name),0) IS NOT NULL)
THEN ' WHERE EmployeeId = @EmployeeId AND Name = @Name;'
WHEN (NULLIF(LEN(@EmployeeId),0) IS NULL AND NULLIF(LEN(@Name),0) IS NOT NULL)
THEN ' WHERE Name = @Name;'
WHEN (NULLIF(LEN(@EmployeeId),0) IS NOT NULL AND NULLIF(LEN(@Name),0) IS NULL)
THEN ' WHERE EmployeeId = @EmployeeId;'
ELSE ''
END;
EXECUTE sp_executesql @sql, @ParmDefinition, @EmployeeId = @EmployeeId, @Name = @Name;
最后,值得注意的是,对于@EmployeeID为NULL或空白但@Name具有值的情况 - 您将获得扫描。如果你想在这些情况下进行搜索,你会想要另一个看起来像这样的索引:
CREATE NONCLUSTERED INDEX nc_employee2 ON dbo.employee (Name, EmployeeId);