2011-10-12 57 views
-1

請參閱下列SQL語句:Neater SQL查詢處理可選的WHERE子句過濾器

有沒有更好的方法來做到這一點,我消除了case語句?

select * from Customer 
where FirstName like ISNULL('ja','') + '%' 
AND [EmailId] LIKE ISNULL('[email protected]','') 
    + CASE when '[email protected]' = '' then '%' else '' end 
+2

任何你爲什麼要合併非空常量的原因?你的意思是IsNull(Customer.Email,'')? – StuartLC

+0

它也看起來像你試圖在SQL中做得更多,而不是必要的。我認爲你是從一些代碼執行它(它看起來生成)?如果是這樣的話,那麼在這裏就可以更好地完成isnull/case語句。 – Thor84no

回答

1

基於@ Thor84no的觀察,我已經參數化查詢(假設產生它的代碼),並假設下列要求:

  • 兩個@firstName和@Email是可選
  • 如果@Firstname不爲空或空白,則始終將其後綴爲%並進行類似操作,否則應用虛擬過濾器(LIKE'%')
  • 如果@Email不爲空或空白,請執行精確搜索(如@ EMAIL),否則應用虛擬過濾器(LIKE'%')

所以parameterises像這樣:

DECLARE @FirstName NVARCHAR(100) 
DECLARE @EmailId NVARCHAR(100) 
SET @FirstName = 'ja' 
SET @EmailId = '[email protected]' 

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是空的情況下 - 你需要的最後一行改爲

+ CASE when IsNull(@EmailId, '') = N'' then N'%' else N'' end 

代碼的查詢計劃相當不錯的 - 它永遠是WHERE姓LIKE「..%」 AND EMAILID像「..」(或EMAILID LIKE‘%’) - 這大概就是爲什麼代碼生成器做這個。

雖然誘人做下面的可讀性,在「或」傷害了查詢計劃,並通常會導致表/索引掃描

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在大量參數可選的情況下通常比Stored Proc更具優勢。 通過使用參數化的SQL,查詢計劃仍然可以被緩存,並且該查詢受到防止SQL注入攻擊的保護。比較

DECLARE @FirstName NVARCHAR(100) 
DECLARE @EmailId NVARCHAR(100) 
SET @FirstName = 'ja' 
SET @EmailId = '[email protected]' 

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)', @[email protected], @[email protected]