锋利的SQL2014:SQL的同时操作概念

 摘自作者新书《锋利的SQL》(第2版),网购京东:http://item.jd.com/11692900.html

需要注意的是,SQL有一个称作同时操作(all-at-onceoperations)的概念,即出现在同一逻辑处理阶段的所有表达式在同一时间点进行逻辑计算。之所以要介绍这个概念,因为不注意此问题,容易产生一些列名的引用错误。例如,你不能在SELECT子句中引用同一SELECT子句指定的列别名,即使它直观地看起来能够这样做。请考虑下面的查询。

USE AdventureWorks2014;

GO

SELECT SalesOrderID, 

 YEAR(OrderDate) AS OrderYear,

  OrderYear +1 AS NextYear

FROM Sales.SalesOrderHeader;

SELECT列表中第3个表达式对列别名OrderYear的引用是无效的,即使引用表达式出现在别名分配之“后”。原因是SELECT列表中的表达式在逻辑上没有计算顺序,列表是一个表达式组,在逻辑级别,SELECT列表中的所有表达式在同一时间点计算。因此,此查询会生成以下错误。

消息 207,级别 16,状态 1,第 3

列名 'OrderYear'无效。

这是关于同时操作的另外一个例子:假设有一个T1表,具有col1col2两个整数列,希望返回col2/col1大于2的所有行。因为有可能表中行的col1是等于0的,你需要确保不存在这种情况,否则,会由于除以零错误导致查询失败。所以,使用以下格式编写一个查询。

SELECT col1, col2

FROM dbo.T1

WHERE col1 <> 0 AND col2/col1 > 2;

你很有可能假定SQL Server从左到右计算此表达式。如果表达式col1<>0的计算结果为FALSESQL Server会短路,也就是说,它不会计算表达式col2/col1>2,因为此时它知道整个表达式是FALSE。所以你可能会认为此查询不会导致除以零错误。

SQL Server不支持短路,基于标准SQL的同时操作概念,SQL Server可以按任意顺序自由处理WHERE子句中的表达式。SQL Server通常基于成本估计对此做出决定,即通常是成本低的表达式先计算。可以看到,如果SQL Server决定首先处理表达式col2/col1>2,此查询可能会因除以零错误而失败。

这里有几种方法可以避免执行失败。例如,CASE表达式中的WHEN子句的计算顺序是有保证的。所以可以按如下方式修改查询。

SELECT col1, col2

FROM dbo.T1

WHERE

  CASE

    WHEN col1= 0 THEN 'no'

    WHENcol2/col1 > 2 THEN 'yes'

    ELSE 'no'

  END ='yes';

col1等于0的行中,第1WHEN子句计算结果为TRUE,且CASE表达式返回字符串“no”。只有在第1CASE表达式的计算结果不为TRUE时(即col1不等于0),执行第2WHEN子句,检查表达式col2/col1>2是否计算为TRUE。如果是,CASE表达式返回字符串“yes”。所有其他情况,CASE表达式返回字符串“no”。只有在CASE表达式的结果等于字符串“yes”时,WHERE子句中的谓语返回TRUE。这意味着这里绝不会尝试除以零。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值