我必须写一个存储过程,其中我必须在姓氏的基础上找到表中的值,姓氏搜索条件可以是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”的复杂性。 请建议我做什么。
答案 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)
注意:
=
,你在@lastNameCriteria
做出任何假设,这就是为什么它被测试两个空值而不是其他两个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))