2011-02-22 76 views
0

我必須寫一個存儲過程,其中我必須根據姓氏從表中找到值,姓氏搜索條件可以是精確的,開頭的或語音的。 SP會像 -Where子句中的情況?

SELECT * FROM Person  
    WHERE (
     CASE @lastNameCriteria 
     WHEN 'EXACT' THEN Person.LastName = @LastName 
     WHEN 'BEGIN' THEN Person.LastName like @LastName 
     ELSE SOUNDEX(tblPerson.LastName) LIKE SOUNDEX(@lastName))      

我不知道上面的查詢將在SQL放棄。我不想使用動態查詢,我不能使用「IF ELSE」,因爲可能有一些其他標準,如FirstNameCriteria,MiddleNameCriteria,這會增加「IF ELSE」的複雜性。 請建議我該怎麼做。

+0

我將它編輯爲與工作非常接近的東西 - 添加了一個單詞 - END - 並刪除了CASE參數和左paren。 – dkretz 2011-02-22 18:41:57

+5

@le dorfier - 請發佈一個答案,而不是**修復**問題。如果我們解決這個問題,那麼答案將不再有意義,甚至是必要的! – RichardTheKiwi 2011-02-22 19:08:08

回答

3

可以正常使用CASE語句這樣

SELECT * 
FROM Person 
WHERE 
    CASE @lastNameCriteria 
    WHEN 'EXACT' THEN 
     CASE WHEN Person.LastName = @LastName THEN 1 END 
    WHEN 'BEGIN' THEN 
     CASE WHEN Person.LastName like @LastName THEN 1 END 
    ELSE 
     CASE WHEN SOUNDEX(tblPerson.LastName) = SOUNDEX(@lastName) THEN 1 END 
    END = 1 

哪樣 SQL Server來在處理嵌入條件之前評估@lastNameCriteria。您也可以使用多個OR子句,憑藉@lastNameCriteria與字符串文字進行比較將導致short-circuit布爾評估 - 除非@lastNameCriteria匹配,否則不評估涉及列比較的部分。

SELECT * 
FROM Person 
WHERE 
(@lastNameCriteria = 'EXACT' AND Person.LastName = @LastName) 
OR 
(@lastNameCriteria = 'BEGIN' AND Person.LastName like @LastName) 
OR 
(isnull(@lastNameCriteria,'') NOT IN ('EXACT','BEGIN') 
AND SOUNDEX(tblPerson.LastName) = SOUNDEX(@lastName)) 
--option(recompile) 

注:

  1. 不要(必須)使用LIKE的SOUNDEX之間,這是一個簡單的=,你是後
  2. 我做了關於@lastNameCriteria任何假設這就是爲什麼它被測試爲空值而不是在另外兩個
  3. 如果你擔心參數嗅探或不正確的查詢計劃, t option (recompile)位。爲這樣簡單的查詢規劃(每次)應該花費很少的時間。
4

不要在一個單一的SELECT中這樣做,你將會失去優化器提出合理執行計劃的機會。使用三個不同的SELECT來代替:

IF @lastNameCriteria = 'EXACT' THEN 
    SELECT * FROM Person WHERE Person.LastName = @LastName 
ELSE IF @lastNameCriteria = 'BEGIN' THEN 
    SELECT * FROM Person WHERE Person.LastName like @LastName 
ELEE 
    SELECT * FROM Person WHERE SOUNDEX(tblPerson.LastName) LIKE SOUNDEX(@lastName) 

通過這種方式,查詢優化器可以創建各種情況下適當的計劃,並在最起碼,使用索引的確切情況。

+1

+1有時,程序員很難記住DRY不適用於SQL。 – Matthew 2011-02-22 18:40:39

+0

@Matthew:是。不幸的是,SQL是70年代設計人員喜歡的一種冗長的語言,與今天的代碼重用意識,DRY意識和lambda募集開發人員完全脫節。 – 2011-02-22 18:51:47

2

要回答的任擇議定書的問題,你可以做這樣的:

SELECT * FROM Person  
WHERE 
    (@lastNameCriteria = 'EXACT' and Person.LastName = @LastName) or 
    (@lastNameCriteria = 'BEGIN' and Person.LastName like @LastName) or 
    (@lastNameCriteria = 'SOUNDEX' and SOUNDEX(tblPerson.LastName) LIKE SOUNDEX(@lastName)) 
相關問題