SQL Server2005杂谈(1):使用公用表表达式(CTE)简化嵌套SQL

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,独享型 2核4GB
简介:
本文为原创,如需转载,请注明作者和出处,谢谢!

     先看下面一个嵌套的查询语句:

select  *  from person.StateProvince  where CountryRegionCode  in 
         ( select CountryRegionCode  from person.CountryRegion  where Name  like  ' C% ')

     上面的查询语句使用了一个子查询。虽然这条 SQL 语句并不复杂,但如果嵌套的层次过多,会使 SQL 语句非常难以阅读和维护。因此,也可以使用表变量的方式来解决这个问题, SQL 语句如下:

declare  @t  table(CountryRegionCode  nvarchar( 3))
insert  into  @t(CountryRegionCode)  ( select CountryRegionCode  from person.CountryRegion  where Name  like  ' C% ')

select  *  from person.StateProvince  where CountryRegionCode 
                      in ( select  *  from  @t)

    虽然上面的SQL语句要比第一种方式更复杂,但却将子查询放在了表变量@t中,这样做将使SQL语句更容易维护,但又会带来另一个问题,就是性能的损失。由于表变量实际上使用了临时表,从而增加了额外的I/O开销,因此,表变量的方式并不太适合数据量大且频繁查询的情况。为此,在SQL Server 2005中提供了另外一种解决方案,这就是公用表表达式(CTE),使用CTE,可以使SQL语句的可维护性,同时,CTE要比表变量的效率高得多。

     下面是 CTE 的语法:

[  WITH <common_table_expression> [ , ] ]
<common_table_expression >:: =
        expression_name  [  ( column_name [ , ] ) ]
     AS
        ( CTE_query_definition )

    现在使用CTE来解决上面的问题,SQL语句如下:

with
cr  as
(
     select CountryRegionCode  from person.CountryRegion  where Name  like  ' C% '
)

select  *  from person.StateProvince  where CountryRegionCode  in ( select  *  from cr)


    其中cr是一个公用表表达式,该表达式在使用上与表变量类似,只是SQL Server 2005在处理公用表表达式的方式上有所不同。

    在使用CTE时应注意如下几点:
1. CTE后面必须直接跟使用CTESQL语句(如selectinsertupdate等),否则,CTE将失效。如下面的SQL语句将无法正常使用CTE


with
cr  as
(
     select CountryRegionCode  from person.CountryRegion  where Name  like  ' C% '
)
select  *  from person.CountryRegion   --  应将这条SQL语句去掉
--
 使用CTE的SQL语句应紧跟在相关的CTE后面 --
select  *  from person.StateProvince  where CountryRegionCode  in ( select  *  from cr)

2. CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下面的SQL语句所示:

with
cte1  as
(
     select  *  from table1  where name  like  ' abc% '
),
cte2  as
(
     select  *  from table2  where id  >  20
),
cte3  as
(
     select  *  from table3  where price  <  100
)
select a. *  from cte1 a, cte2 b, cte3 c  where a.id  = b.id  and a.id  = c.id


3. 如果CTE的表达式名称与某个数据表或视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE,当然,后面的SQL语句使用的就是数据表或视图了,如下面的SQL语句所示:

--   table1是一个实际存在的表

with
table1  as
(
     select  *  from persons  where age  <  30
)
select  *  from table1   --   使用了名为table1的公共表表达式
select  *  from table1   --   使用了名为table1的数据表

4. CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。

5. 不能在 CTE_query_definition 中使用以下子句:

1COMPUTE  COMPUTE BY

2ORDER BY(除非指定了 TOP 子句)

3INTO

4)带有查询提示的 OPTION 子句

5FOR XML

6FOR BROWSE

6. 如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,如下面的SQL所示:

declare  @s  nvarchar( 3)
set  @s  =  ' C% '
;   --  必须加分号
with
t_tree  as
(
     select CountryRegionCode  from person.CountryRegion  where Name  like  @s
)
select  *  from person.StateProvince  where CountryRegionCode  in ( select  *  from t_tree)

    CTE除了可以简化嵌套SQL语句外,还可以进行递归调用,关于这一部分的内容将在下一篇文章中介绍。

下一篇:
SQL Server2005杂谈(2):公用表表达式(CTE)的递归调用

本文转自银河使者博客园博客,原文链接http://www.cnblogs.com/nokiaguy/archive/2009/01/31/1381562.html如需转载请自行联系原作者


银河使者

相关实践学习
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
相关文章
|
29天前
|
SQL 关系型数据库 MySQL
mysql sql语句删除一个库下的所有表
mysql sql语句删除一个库下的所有表
22 1
|
5天前
|
SQL 存储 测试技术
|
16天前
|
SQL 存储 数据库
SQL 撤销索引、撤销表以及撤销数据库
SQL 撤销索引、撤销表以及撤销数据库
22 4
|
28天前
|
SQL 存储 关系型数据库
MySQL数据库——SQL(1)-SQL通用语法、SQL分类、DDL(数据库操作、表操作)
MySQL数据库——SQL(1)-SQL通用语法、SQL分类、DDL(数据库操作、表操作)
26 1
|
1月前
|
SQL 存储 缓存
揭秘SQL中的公用表表达式:数据查询的新宠儿
揭秘SQL中的公用表表达式:数据查询的新宠儿
26 2
|
2月前
|
SQL 关系型数据库 MySQL
sql怎么创建数据库表,SQL(Struct
SQL是管理关系型数据库的标准语言,用于创建、维护和查询数据库表。创建表的基本步骤包括:选择数据库(如MySQL等),使用CREATE TABLE语句定义表结构,指定字段属性和数据类型,设置约束(如主键、唯一键),创建索引以提升查询性能,最后以分号结束语句完成创建。此外,还可使用ALTER TABLE修改表,DROP TABLE删除表,以及其他SQL语句进行查询、插入、更新和删除操作,有效管理数据库。
38 3
|
1月前
|
SQL 关系型数据库 MySQL
sql删除数据库中表
在SQL中,如果你想删除(或称为\以下是基本语法: ```sql DROP TABLE 表名称; ``` 例如,如果你有一个名为 `employees` 的表,并且你想删除它,你可以执
|
2月前
|
SQL 数据库
Sql server 表管理(创建 修改 删除)
Sql server 表管理(创建 修改 删除)
|
2月前
|
SQL 流计算 API
实时计算 Flink版产品使用合集之ClickHouse-JDBC 写入数据时,发现写入的目标表名称与 PreparedStatement 中 SQL 的表名不一致如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
35 0
|
2月前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL表达式:数据的魔法公式
【4月更文挑战第19天】探索Oracle PL/SQL表达式,体验数据的魔法公式。表达式结合常量、变量、运算符和函数,用于数据运算与转换。算术运算符处理数值计算,比较运算符执行数据比较,内置函数如TO_CHAR、ROUND和SUBSTR提供多样化操作。条件表达式如CASE和NULLIF实现灵活逻辑判断。广泛应用于SQL查询和PL/SQL程序,助你驾驭数据,揭示其背后的规律与秘密,成为数据魔法师。