2011-02-22 109 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))