一:逻辑查询处理
(8)SELECT (9)DISTINCT (11) <TOP_specification> <select_list> (1)FROM <left_table> (3)<join_type> JOIN <right_table> (2)ON <join_condition> (4)WHERE <where_condition> (5)GROUP BY <group_by_list> (6)WITH {cube|rollup} (7)HAVING <having_condition> (10)ORDER BY <order_by_list> |
各个步骤分析(查询语句未涉及的步骤将跳过)
(1) FROM: 对From子句中的左右表(如果有2个表的话,甚至涉及多表查询)执行笛卡尔积(交叉联接),生成VT1(虚拟表1)
(2) ON:对VT1应用ON筛选器,只有join_condition为True,才被插入VT2
(3) OUTER:涉及外部联接,保留表的数据(非保留表为NULL)插入VT2生成VT3
(4) Where:对VT3执行Where筛选器,只有where_condition为TRUE,才被插入VT4
(5) GROUP BY:对VT4分组,得到VT5
(6) 把超值插入VT5,生成VT6
(7) HAVING: 对VT6执行Having筛选器,只有Having_condition为TRUE,才被插入VT7
(8) SELECT:产生VT8
(9) DISTINCT: 删除重复行,产生VT9(不能和group by同用,既然都分组了,再用distinct就多余了)
(10)ORDER BY:排序,生成游标(VT10)
(11)TOP:生成VT11,返回结果表
SQL重要特性—三值逻辑(True,False,Unknown)
1:NULL值通常表示丢失或不相关的值,当比较NULL值和另外的值(可能也是null值)时,逻辑结果总是UNKNOWN.我们都知道 not true=false,not false=true,而not unknown还是unknown!
2:筛选器(ON,HAVING,WHERE)把UNKNOWN当作false处理.举个例子:对2个null进行比较,由于逻辑结果为unknown,所以在筛选器中一个null不等于另外的null值.
3:CHECK约束将unknown当做true处理.举个例子:对col1列约束值>0,当插入null值的时候,(null>0)这样的逻辑结果为unknown(前面黑色注明处已说明!),check将其当做true处理,所以可以插入null的值.
4:unique约束,group by子句,order by子句将null视为相等
理解同时操作
表testdb的数据定义语言(DDL)和示例数据 use tempdb if object_id('testdb') is not null drop table testdb; GO create table testdb( c1 int, c2 int ) insert into testdb(c1,c2) values(1,100); insert into testdb(c1,c2) values(2,200); insert into testdb(c1,c2) values(3,300); |
在大多数编程语言中,交换2个数可能需要用到第三个数.对于下面的操作
update testdb set c1=c2,c2=c1
(已交换2列数据)
就好象同时操作,在sql语句未完成前是不会修改表中数据的.
update testdb set c1=c1+(select max(c1) from testdb);
所以也不用担心max(c1)会持续变化!
二:物理查询处理
名词解析:
Include actual Execution Plan 包含实际的执行计划
Nested Loops 嵌套循环
Index Seek 索引查找
Aggregate 流聚合
Compute Scalar 计算标量
Filter 筛选器
数据库引擎处理查询或存储过程,分为2部分.编译生成查询计划和执行查询计划
编译由分析,代数化,优化(优化器)组成,将查询计划保存在过程缓存中,最后执行引擎将该计划转换为可执行的形式,生成查询结果!以后执行相同的查询或存储过程,将直接重用缓存好的计划来执行,不需要再编译了
use Northwind
--查询来自城市'London'订单>5的消费者及其订单数量
Select C.CustomerID,Count(OrderID) As NumsOrders
From Customers AS C Left Outer Join Orders AS O
on C.CustomerID=O.CustomerID
where C.City='London'
Group By C.CustomerID
Having Count(OrderID)>5
Order By NumsOrders