2012-05-18 46 views
1

我有两个可选参数empName,empLoc。这两个参数都可以为空,空或具有某些值。如果两者都有值,我将不得不获得所有值,如果empName有值,那么我只需要获取值,其中empName等于传递参数@empName,并且与@empLoc相同。我知道我可以在同一个存储过程中编写单独的sql,但是我想使用CASE子句来完成它,因为它将保存大部分重复的代码。然而,我在设置查询时遇到了问题。我知道这是CASE条款。 这里是我的查询看起来是这样的:SQL CASE在Where子句中?

SELECT 
    EmpID, 
    EmpDept 
FROM Employee 
WHERE TimeStamp = @timeStamp 
**AND (CASE 
     WHEN DATALENGTH(@empName) > 0 THEN EmployeeName LIKE '%' [email protected]+'%' 
     ELSE 
     EmployeeLocation LIKE '%' [email protected]+'%' 
     END)** 

注:即时通讯已经在做这些参数的空检查。此外,只有在@empName或@empLoc具有某些值的情况下,该查询才会运行。

任何建议如何解决这个问题?

+1

你没有说你的问题是什么? – ilanco

+0

为什么你甚至使用' LIKE'?这些信息不应该存储在某个地方吗? – swasheck

回答

4

事实上,你必须把DATALENGTH(@empName)< = 0的第二部分,因为CASE意味着一个异或。所以,正确的应该是:

SELECT 
    EmpID, 
    EmpDept 
FROM Employee 
WHERE TimeStamp = @timeStamp 
AND 
(
    (DATALENGTH(@empName) > 0 AND EmployeeName LIKE '%' [email protected]+'%') 
     OR 
    (DATALENGTH(@empName) <= 0 AND EmployeeLocation LIKE '%' [email protected]+'%') 
) 
+0

我喜欢这种通常被称为“捕获所有查询”的模式。确保在语句的末尾添加一个OPTION(RECOMPILE),以便查询优化器可以更好地完成工作,并可能避免(非常)执行不良的查询。更多信息:http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/ – buckley

-1

你不需要case when声明对于这个问题

SELECT 
    EmpID, 
    EmpDept 
FROM Employee 
WHERE TimeStamp = @timeStamp 
AND 
    ((DATALENGTH(@empName) > 0 AND EmployeeName LIKE '%' [email protected]+'%') 
     OR 
     (DATALENGTH(@empName) = 0 AND EmployeeLocation LIKE '%' [email protected]+'%')) 
+0

DATALENGTH(@empName)= 0应该是DATALENGTH(@empName)<= 0 – buckley

+0

DATALENGTH永远不会返回负数。所以“=”就足够了。你能写一段文字有否定的长度吗? –

+0

这是一个你假设我假设,因为它不在http://msdn.microsoft.com/en-us/library/ms173486.aspx文档中请注意,我同意这不太可能,但如果此函数返回负数数字来表示异常?保持它们在逻辑上相当似乎更好。 – buckley

1

CASE是一个返回值的表达式:

where TimeStamp = @timeStamp and 
    CASE WHEN DATALENGTH(@empName) > 0 AND EmployeeName LIKE '%' [email protected]+'%' THEN 1 
    WHEN EmployeeLocation LIKE '%' [email protected]+'%' THEN 1 
    ELSE 0 
    END = 1 
+0

这将导致扫描。使用蒂亚戈建议的模式会更好。 – buckley

+0

@buckley - 这种方法和Tiago的将在TimeStamp上使用索引,如果有的话。任何以百分号开头的LIKE模式都需要扫描。我错过了什么? – HABO

+0

类似于以%开头的模式,仍然可以从列上的非聚集索引中受益,因为它会导致扫描的数据更少(我刚才测试过)。 对于上面的扫描,我的意思是一个普通扫描(在堆或聚簇索引扫描的情况下进行表扫描),如果您在该位置给它一个CASE,优化器将被强制执行扫描。 Tiago将where子句转换为SARG,它为优化程序提供了更多选项(即使优化程序可能决定在该时间点不使用索引*)。 – buckley

0

您可以使用LEN函数,如果要修剪空间

SELECT DATALENGTH(' ') --Result is 1 
SELECT LEN(' ') -- Result is 0