SQL Server 2005 技术内幕之T-SQL查询——逻辑查询处理(上)

      SQL 不同于其他编程语言的最明显特征是处理代码的顺序。在大多数编程语言中,代码按编码顺序被处理,但在SQL中,第一个被处理的是from字句,尽管select语句第一个出现,但几乎总是在最后被处理。

      每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入。这些虚拟表对调用者不可用。只有最后一步生成的表才会返回给调用者。

     查询的一般形式:

View Code
1 select distinct <Top_specification> <select_list>
2 from <left_table>
3 <join_type> join <right_table>
4 on <join_condition>
5 where <where_condition>
6 group by <group_by_list>
7 with {cube|rollup}
8 having <having_condition>
9 order by <order_by_list>

 

  逻辑查询处理阶段简介:

  1. from:对from字句中的前两个表执行笛卡尔积,即交叉联接,生成虚拟表VT1.
  2. on:对VT1应用on筛选器,只有那些使<join_condition> 为真的行被插入VT2.
  3. outer (join):如果指定了outer join(相对于cross join或者inner join),保留表中未找到匹配的行将作为外部行添加到VT2,生成VT3,如果from子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行1-3步,直到处理完所有的表为止。
  4. where:对VT3应用where筛选器,只有使<where_condition>为true的行被插入VT4.
  5. Group by:按group by子句中的列列表对VT4中的行分组,生成VT5.
  6. Cube | Rollup:把超组插入VT5,生成VT6.
  7. Having:对VT6应用having筛选器,只有使<having_condition>为true的组被插入VT7.
  8. Select:处理select列表,产生VT8.
  9. Distinct:将重复的行从VT8中删除,生成VT9.
  10. Order by:将VT9中的行按order by子句中的列列表排序,生成一个游标VC10.
  11. Top:从VC10的开始处选择指定数量或比例的行,生成表VT11,并返回给调用者。

      SQL中特有的特性——三值逻辑:true,false,unknown,其中unknown逻辑值通常出现在包含null值的逻辑表达式中。Null值通常表示丢失或不相关的值。当比较丢失值和另一个值(这个值可能也是null)时,逻辑结果总是unknown。PS:unknown的否定值还是unknown。

      Unknown逻辑结果和null在不同的语言元素中被区别对待,例如,所有的查询筛选器 (on, where, having) 都把unknown当作false处理,使筛选器为unknown的行会被排除在结果集之外。而check约束中的unknown值被当作true对待。

      在筛选器中比较两个null值得到的是unknown,它会被当作false处理,就好像其中一个null不等于另一个null。而unique约束、排序操作和分组操作认为两个null值相等。

1、 如果表中有一列定义了unique约束,将无法向表中插入该列值为null的两行。

2、 Group by 字句把所有null值分到一起。

3、 Order by 字句把所有null值排列在一起。      

       对于包含outer join字句的查询,有一个让人困惑的问题,到底是在on筛选器还是在where筛选器中指定逻辑表达式。二者的主要区别是on在添加外部行之前被应用,而where在添加外部行之后被应用,on筛选器对保留表中部分行的移除并不是最终的,因为添加外部行的时候可能会再被添加回来,而where对行的移除是最终的。PS:只有在使用外部链接的时候,on和where子句才会存在这种逻辑差别。

       在select列表中创建的别名不能在执行select之前的任何步骤中使用。实际上,表达式别名甚至不能用于select列表中的其他表达式,即不可同时操作。因此,一般情况下,order by是第一步也是唯一一步可以使用select列表中的列别名的步骤。

       如果指定了distinct,order by子句中的表达式只能访问VT9返回的虚拟表,也就是说,只能按已经选择的列排序。这也是为什么指定了distinct就不能访问未返回的表达式的原因。

       Order by不返回有效的表,而是返回一个游标。原因如下:SQL是基于集合理论的,集合不会预先对它的行排序,它只是成员的逻辑集合,成员的顺序无关紧要。对表进行排序的查询可以返回一个对象,包含按特定物理顺序组织的行。这个对象就称为游标。

      尽管SQL并不为表中的行呈现特定的顺序,但它却按特定顺序维护列的位置。指定select * ( 尽管因种种原因这并不是好习惯)可以确保按特定的顺序返回列。

     因为order by不返回表,所有使用它的查询不能用作表表达式。表表达式包括:视图、内联表值函数、子查询、派生表和共用表达式。它的结果必须返回给期望得到物理记录集的客户端应用程序。

     记住,不要为表中的行假设任何特定的顺序,即,除非确实需要有序行,否则不要指定order by子句。排序是有成本的,SQL Server需要执行有序索引扫描或使用排序运算符。

      只有指定了Top选项,才能在表表达式中使用带有order by子句的查询,换句话说,同时指定了Top和order by子句的查询可以返回一个关系结果。具有讽刺意味的是,使用了非标准非关系的Top选项后,本来应该返回游标的查询却返回了一个关系结果。

 

转载于:https://www.cnblogs.com/Jennifer/articles/2335958.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值