在Where子句中的情况?

时间:2011-02-22 18:34:19

标签: sql sql-server

我必须写一个存储过程,其中我必须在姓氏的基础上找到表中的值,姓氏搜索条件可以是Exact,Begin with或Phonetic。 SP就像 -

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”的复杂性。 请建议我做什么。

3 个答案:

答案 0 :(得分:4)

不要在sinlge 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)

这样查询优化器可以为每个案例创建适当的计划,并且至少使用EXACT案例的索引。

答案 1 :(得分: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. 不要(必须)在SOUNDEX之间使用 LIKE ,这是一个简单的=,你在
  2. 之后
  3. 我没有对@lastNameCriteria做出任何假设,这就是为什么它被测试两个空值而不是其他两个
  4. 如果您担心参数嗅探或查询计划不正确,请取消注释option (recompile)位。规划(每次)这样一个简单的查询应该花费不大的时间。

答案 2 :(得分:2)

要回答OP的问题,可以这样做:

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))