使用CASE表达式替代SQL Server中的动态SQL

系统 1910 0
原文: 使用CASE表达式替代SQL Server中的动态SQL

翻译自:

http://www.mssqltips.com/sqlservertip/1455/using-the-case-expression-instead-of-dynamic-sql-in-sql-server/?utm_source=dailynewsletter&utm_medium=email&utm_content=headline&utm_campaign=2012620

问题:

在决定IF/ELSE时,会有很多UPDATE查询,某些情况下我使用游标,但循环几千行数据的UPDATE时,会花费非常多的事件。我也使用一些动态SQL来处理一些查询参数。除此之外,还有更好的选择吗?

 

 

解决方案:

CASE表达式是在解决SQLServer查询问题上的一个强大的工具。你可能感觉到它在SELECT语句中的用法类似于IF/ELSE的处理。但是,相对与IF/ELSE,CASE表达式却没有那么多限制。

在以下代码中将展示CASE表达式的用处:

l  消除在UPDATE行时的游标循环。

l  在使用聚集函数时,执行特殊处理。

l  不使用动态SQL的动态ORDER BY 和WHERE子句

让我们看看以下例子:

首先,先创建一个名为Customer的表并插入数据:

CREATE TABLE dbo . Customer  

(

customerid INT IDENTITY PRIMARY KEY ,  

firstname VARCHAR ( 40 ) NOT NULL,  

lastname VARCHAR ( 40 ) NOT NULL,  

statecode VARCHAR ( 2 ) NOT NULL,  

totalsales money NOT NULL DEFAULT 0.00

)

 

INSERT INTO dbo . Customer ( firstname , lastname , statecode , totalsales )  

SELECT 'Thomas' , 'Jefferson' , 'VA' , 100.00

 

INSERT INTO dbo . Customer ( firstname , lastname , statecode , totalsales )  

SELECT 'John' , 'Adams' , 'MA' , 200.00

 

INSERT INTO dbo . Customer ( firstname , lastname , statecode , totalsales )  

SELECT 'Paul' , 'Revere' , 'MA' , 300.00

 

INSERT INTO dbo . Customer ( firstname , lastname , statecode , totalsales )  

SELECT 'Ben' , 'Franklin' , 'PA' , 400.00

GO

 

示例1:

由于报表展示的需要,在一个非范式化的表中增加一个所在州描述列。现在,你可以使用游标和来循环更新每一行。但是游标往往是性能杀手。你也可以使用大量UPDATE语句,但是这将导致程序非常臃肿。

对此,可以在一个UDPATE语句的SET 子句中使用带有CASE关键字来实现更有效的操作:

ALTER TABLE  dbo.Customer  ADD  statedescription  VARCHAR ( 50 ) NULL 
GO 
UPDATE  dbo.Customer 
SET  stateDescription  CASE  WHEN  statecode  'MA'  THEN  'Massachusetts' 
WHEN  statecode  'VA'  THEN  'Virginia' 
WHEN  statecode  'PA'  THEN  'Pennsylvania' 
ELSE  NULL 
END   

 

示例 2

当我们需要统计所有来自 Massachusetts 州用户的数量及他们的平均总消费时。我们能限制查询在仅仅是 Massachusetts 的客户。但这将使得在得到用户总数时语句变得臃肿,为此,可以在聚集函数中使用 CASE 表达式来得到特定信息:

SELECT  COUNT (*)  AS  TotalCustomers ,  
SUM ( CASE  WHEN  statecode  'MA'  THEN  ELSE  NULL  END AS  TotalMassCustomers ,  
AVG ( CASE  WHEN  statecode  'MA'  THEN  totalsales  ELSE  NULL  END AS  TotalMassSales  
FROM  dbo.Customer 

因为在聚集函数中,NULL值不参与计算,所以可以通过这个特性来获得我们想要的数据。

 

示例3:

    第三个案例来自于我们的桌面,我们需要一个存储过程来被应用程序调用,但用户想根据第一个名字或者第二个名字排序。其中一个方法是使用动态SQL来解决这个问题,但是我们可以使用CASE来等价实现:

CREATE PROCEDURE dbo . getCustomerData @sortby VARCHAR ( 9 ), @sortdirection CHAR ( 4 )

AS

SET nocount ON

 

SELECT customerid , firstname , lastname , statecode , statedescription , totalsales

FROM dbo . Customer

ORDER BY  

CASE @sortdirection

     WHEN 'asc' THEN

      CASE @sortby  

       WHEN 'firstname' THEN firstname  

       WHEN 'lastname' THEN lastname  

       END

END  

ASC ,

CASE @sortdirection

      WHEN 'desc' THEN

       CASE @sortby  

       WHEN 'firstname' THEN firstname  

       WHEN 'lastname' THEN lastname  

       END

END

DESC

GO

 

EXEC dbo . getCustomerData 'lastname' , 'desc'

 

示例4:

         最后一个例子中与示例3相似,我们需要改动存储过程去查找特定州的客户,如果该参数被忽略,则返回所有客户的所在州。

ALTER PROCEDURE  dbo.getCustomerData  @sortby  VARCHAR ( 9 ),  @sortdirection  CHAR ( 4 ),  @statecode  VARCHAR ( 2 NULL 
AS  
SET 
nocount  ON  

SELECT 
customerid firstname lastname statecode statedescription totalsales 
FROM  dbo.Customer 
WHERE  statecode  CASE  WHEN  @statecode  IS  NOT NULL  THEN  @statecode  
ELSE  statecode 
END  
ORDER BY 
 
CASE  @sortdirection 
      WHEN  'asc'  THEN  
      
CASE  @sortby  
        WHEN  'firstname'  THEN  firstname  
        WHEN  'lastname'  THEN  lastname  
        END  
END 
 
ASC

CASE  @sortdirection 
       WHEN  'desc'  THEN  
       
CASE  @sortby  
        WHEN  'firstname'  THEN  firstname  
        WHEN  'lastname'  THEN  lastname  
        END  
END
 
DESC
 
GO 

EXEC  dbo.getCustomerData  'lastname' 'desc' 'MA' 

使用CASE表达式替代SQL Server中的动态SQL


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论