基於@ 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]
任何你爲什麼要合併非空常量的原因?你的意思是IsNull(Customer.Email,'')? – StuartLC
它也看起來像你試圖在SQL中做得更多,而不是必要的。我認爲你是從一些代碼執行它(它看起來生成)?如果是這樣的話,那麼在這裏就可以更好地完成isnull/case語句。 – Thor84no