请参阅下面的SQL语句:
有没有更好的方法来消除案例陈述?
select * from Customer
where FirstName like ISNULL('ja','') + '%'
AND [EmailId] LIKE ISNULL('jaisonshereen@gmail.com1','')
+ CASE when 'jaisonshereen@gmail.com1' = '' then '%' else '' end
答案 0 :(得分:1)
基于@ Thor84no的观察,我已经参数化了你的查询(假设它是代码生成的)并且假设了以下要求:
所以它的参数设置如下:
DECLARE @FirstName NVARCHAR(100)
DECLARE @EmailId NVARCHAR(100)
SET @FirstName = 'ja'
SET @EmailId = 'jaisonshereen@gmail.com1'
select * from Customer
where FirstName like ISNULL(@FirstName,'') + N'%'
AND [EmailId] LIKE ISNULL(@EmailId, N'')
+ CASE when @EmailId = N'' then N'%' else N'' end
我相信有一种情况你不会处理,即如果@Email为NULL - 你需要将最后一行更改为
+ CASE when IsNull(@EmailId, '') = N'' then N'%' else N'' end
你的代码的查询计划相当不错 - 它总是WHERE FirstName LIKE'..%'和EMailId喜欢'..'(或EmailId喜欢'%') - 这可能是代码生成器执行此操作的原因。
虽然为了便于阅读而尝试以下操作很有诱惑力,但“OR”会影响查询计划,并且通常会导致表/索引扫描
select * from Customer
WHERE
(ISNULL(@FirstName, N'') = N'' OR FirstName LIKE @FirstName + N'%')
AND (ISNULL(@EmailId, N'') = N'' OR [EmailId] = @EmailId) -- Assuming ANSI Nulls are ON
因此,虽然你看起来很乱,但它实际上是非常理想的。
出于兴趣,动态SQL(例如由LINQ2SQL,EF等ORMS生成)在大量参数可选的情况下通常比存储过程具有优势。 通过使用参数化SQL,仍可以缓存查询计划,并且可以防止查询受到SQL注入攻击。比较
DECLARE @FirstName NVARCHAR(100)
DECLARE @EmailId NVARCHAR(100)
SET @FirstName = 'ja'
SET @EmailId = 'jaisonshereen@gmail.com1'
DECLARE @SQL NVARCHAR(MAX)
SET @SQL = N'SELECT * FROM Customer '
IF ISNULL(@FirstName,'') <> N'' OR ISNULL(@EmailId, N'') <> N''
SET @SQL = @SQL + N'WHERE ' -- Need to handle the case where neither param provided
IF ISNULL(@FirstName, N'') <> N''
SET @SQL = @SQL + N' FirstName LIKE @FirstName + ''%'''
IF ISNULL(@FirstName,'') <> N'' AND ISNULL(@EmailId, N'') <> N''
SET @SQL = @SQL + N' AND'
IF ISNULL(@EmailId,'') <> N''
SET @SQL = @SQL + N' EmailId = @EmailId' -- Exact match
exec sp_ExecuteSQL @SQL, N'@FirstName NVARCHAR(100), @EmailId NVARCHAR(100)', @FirstName=@FirstName, @EmailId=@EmailId