1、表表达式概述

(1)表表达式(table expression) 是一个命名的查询表达式、代表一个有效的关系表

(2)在DML 中,使用表表达式和使用其他表非常类似

(3)sqlserver 支持4种表表达式: 派生表、公用表达式(CTE)、视图 、内嵌值函数(内嵌TVF)

(4)表表达式没有任何的物理实例化、是虚拟的、内部查询是嵌套 的

(5)使用表表达式的好处是代码逻辑方便有关、与性能无关、表表达式本身不会对性能带来正负影响

2、有效定义表表达式查询需要满足的3个要求

2.1 无法保证顺序

(1)表表达式用于代表一个关系表、关系表的行是无序的,有序那是游标。

(2)如果在表表达式,如派生表中使用order by ,必须使用top 或者 OFFSET 否则报错

(3)即使在 派生表中使用order by ,在外部查询没有使用order by的情况下,查询结果仍然是无序的

2.2 所有列都必须具有名称

(1)在定义表表达式的查询中,必须有名称、如果出现表达式 或者 函数 导致没有名称的列出现,直接报错

2.3所有列名必须唯一

(1)当连表查询、两种表具有相同名称的列,就会到时该表表达式invalid ,此时通过别名解决

3、派生表

(1)派生表 也称子查询表、临时表,是在from 子句中定义的,他们存在的范围是外部查询,一旦外部查询接收,派生表就消失了

(2)派生表的查询需要定义在括号内

(3)使用表表达式的一个好处就是,外部查询可以引用内部查询select 子句中分配的列别名、这就可以绕开where 和 group by 无法使用select子句分配别名的问题

(4)在定义派生表的查询中,可以引用参数,参数可以是例行的能够用于存储过程或函数的变量

declare @empid as int =3;
select orderyear, count(distinct custid) as numcusts
from
(
select year(orderdate) as orderyear, custid
from Sales.Orders
where empid = @empid
) as D
group by orderyear

(5)如果定义的派生表查询需要引用林外一个派生表,这将是一个嵌套派生表。嵌套是常见的编程问题方面、会导致代码复制、可读性差

(6)派生表是定义在外部查询的from 子句中,由于不是外部查询之前就已存在的物理事实,所以无法在同一个from中引用同一个派生表的多个实例

-- 解决方案: 基于同一个子查询的多个派生表
SELECT Cur.orderyear,
Cur.numcusts AS curnumcusts,
Prv.numcusts AS prvnumcusts,
Cur.numcusts - Prv.numcusts AS growth
FROM
(
SELECT YEAR(orderdate) AS orderyear,
COUNT(DISTINCT custid) AS numcusts
FROM Sales.Orders
GROUP BY YEAR(orderdate)
) AS Cur
LEFT OUTER JOIN
(
SELECT YEAR(orderdate) AS orderyear,
COUNT(DISTINCT custid) AS numcusts
FROM Sales.Orders
GROUP BY YEAR(orderdate)
) AS Prv
ON Cur.orderyear = Prv.orderyear + 1;

不能引用同一派生表的多个实例,导致维护多份相同代码,这也是派生表的一个问题

4、公用表表达式(CTE)

(1)公用表表达式(CTE)是表表达式的另一种标准形式,与派生表类似,但具有几个优势

(2)CTE 通过with 语句定义

with USACusts as
(
select custid, companyname
from Sales.Customers
where country = N'USA'
)
select * from USACusts

(3) 表表达式的三个要求,在CTE 中也是都要满足

(4)T-SQL 中with 子句可用于不同的目的,为避免歧义,在with子句用于定义CTE时 ,with前面的分句必须打分号隔开

(5)CTE 和 派生表一样也支持量好难过命名方式、内嵌式 和 外部式

(6)CTE 中也可以使用参数

(7)表面上看CTE 和 派生表只有语义上的区别。但是先定义后使用的特点,解决了嵌套问题

可定义多个CTE ,用分号隔离;

相互引用,不再嵌套;

(8)不能在派生表中的括号内去定义CTE

(9)就外部查询的from子句而言,CTE 在其之前就已经存在了,可以已用同一个CTE 的多个实例,避免了维护多份一样的代码

WITH YearlyCount AS
(
SELECT YEAR(orderdate) AS orderyear,
COUNT(DISTINCT custid) AS numcusts
FROM Sales.Orders
GROUP BY YEAR(orderdate)
)
SELECT Cur.orderyear,
Cur.numcusts AS curnumcusts, Prv.numcusts AS prvnumcusts,
Cur.numcusts - Prv.numcusts AS growth
FROM YearlyCount AS Cur
LEFT OUTER JOIN YearlyCount AS Prv
ON Cur.orderyear = Prv.orderyear + 1;

(10)CTE 支持递归操作,但是递归操作很危险,有可能吧数据库搞崩的,特别是取消了递归次数限制的情况

5、视图(VIEW)

(1)派生表和CTE范围有限、外部查询完成就消失 、无法重复使用

(2)视图和内嵌值函数(TVF)是两种可以重复使用的表达式类型、其定义被存储为数据库对象、永久保存、直到显式删除

(3)其他方便,视图和TVF 和CTE 一样,比如查询时,sql server 都会拓展表表达式的定义、直接查底层的对象

(4)创建视图

create view  Sales.USACusts
as
select
custid, companyname, contactname, contacttitle, address,
city, region, postalcode, country, phone, fax
FROM Sales.Customers
WHERE country = N'USA';

(5)和CTE 一样,视图的别名也有内嵌式 和 外部式两种

(6) 由于视图是数据库的对象,可以控制视图的访问权限、包括select 、insert 、update 、delete 权限

(7) 定义视图是尽量不要使用select * ,因为在创建视图之后,底层对象表发生改变、视图中的列是不会同步的、显式指定列,然后通过alter view 修改视图定义

(8)视图的select 也必须满足表表达式的所有要求 、视图是无法保证行的顺序的、列名称必须唯一且存在

(9)要想查询视图返回有序的结果集,需要在外部查询中进行order by

(10) sql server 2012 尝试通过 orderby xxx offset 0 rows 获取 有序视图,但这是当前的一种优化手段,不能绝对保证有序

(11)获取视图定义(创建视图的sql 就是视图定义)

select OBJECT_DEFINITION(OBJECT_ID('Sales.USACusts'))

(11)视图选项

在创建和更改视图时,可以指定作为视图定义一部分的视图属性 和 视图选项。

①encryption 选项

encryption选项指示sql server 在内部以代码混淆方式存储对象定义文本,代码混淆文本对通过任何目录对象的用户都是不可直接见的,仅对通过特定方法的特权用户可见

-- 修改视图、指定encryption选项 ,修改之后查询视图定义返回NULL
ALTER VIEW Sales.USACusts
WITH ENCRYPTION
AS
SELECT
custid, companyname, contactname, contacttitle, address,
city, region, postalcode, country, phone, fax
FROM Sales.Customers
WHERE country = N'USA';

②schemabinding 选型

schemabinding 选项对视图和UDF可用 ,将“被引用对象的架构和列(就是视图的元数据表和列)” 绑定到 引用对象(视图)的架构中 ,此时不能删除和修改 被引用的列 和对象(不能删除修改元数据表和列)

ALTER VIEW Sales.USACusts
WITH schemabinding,encryption
AS
SELECT
custid, companyname, contactname, contacttitle, address,
city, region, postalcode, country, phone, fax
FROM Sales.Customers
WHERE country = N'USA';

③check option 选项

check option的目的是防止出现视图修改与视图视图塞选的冲突,下面演示该冲突

-- 定义视图,值查来自美国(USA)客户

CREATE VIEW Sales.USACusts
AS
SELECT
custid, companyname, contactname, contacttitle, address,
city, region, postalcode, country, phone, fax
FROM Sales.Customers
WHERE country = N'USA'; -- 通过视图往源数据表Customers表插入一条英国的用户数据
INSERT INTO Sales.USACusts(
companyname, contactname, contacttitle, address,
city, region, postalcode, country, phone, fax)
VALUES(
N'Customer ABCDE', N'Contact ABCDE', N'Title ABCDE', N'Address ABCDE',
N'London', NULL, N'', N'UK', N'012-3456789', N'012-3456789'); -- 冲突出现,此时从视图查询不到刚刚往视图插入的英国用户数据,但是直接去Customers 表中查是有这条数据的
SELECT custid, companyname, country
FROM Sales.USACusts
WHERE companyname = N'Customer ABCDE';

check option 就是解决上述冲突、此时当通过视图插入的数据不满足视图塞选条件,会直接报错

-- 修改视图定义,添加check point 属性
ALTER VIEW Sales.USACusts
WITH SCHEMABINDING
AS
SELECT
custid, companyname, contactname, contacttitle, address,
city, region, postalcode, country, phone, fax
FROM Sales.Customers
WHERE country = N'USA'
WITH CHECK OPTION; -- 测试插入与视图塞选条件不符 的数据,报错
INSERT INTO Sales.USACusts(
companyname, contactname, contacttitle, address,
city, region, postalcode, country, phone, fax)
VALUES(
N'Customer FGHIJ', N'Contact FGHIJ', N'Title FGHIJ', N'Address FGHIJ',
N'London', NULL, N'', N'UK', N'012-3456789', N'012-3456789');

6、内嵌表值函数(TVF)

(1)内嵌TVF 是支持输入参数的可重复使用的表表达式 ,可以理解成参数化视图

(2)定义

-- 创建TVF ,传入客户cid, 查询该客户的订单
create function
dbo.GetCustOrders
(@cid as int) returns TABLE
return
select
orderid, custid, empid, orderdate, requireddate,
shippeddate, shipperid, freight, shipname, shipaddress, shipcity,
shipregion, shippostalcode, shipcountry
from Sales.Orders
where custid = @cid

(3)使用

-- 强烈建议给TVF 取别名,参数在括号内传入
SELECT orderid, custid
FROM dbo.GetCustOrders(1) AS O;

Sql server 表表达式的更多相关文章

  1. SQL Server 表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数

    概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...

  2. SQL Server 表变量和临时表的区别

    SQL Server 表变量和临时表的区别 一.表变量 表变量在SQL Server 2000中首次被引入.表变量的具体定义包括列定义,列名,数据类型和约束.而在表变量中可以使用的约束包括主键约束,唯 ...

  3. 09Microsoft SQL Server 表数据插入,更新,删除

    Microsoft SQL Server 表数据插入,更新,删除 向表中插入数据 INSERT INTO insert into tb1 values(0004,'张凤凤') insert into ...

  4. 在一个SQL Server表中的多个列找出最大值

    在一个SQL Server表中一行的多个列找出最大值 有时候我们需要从多个相同的列里(这些列的数据类型相同)找出最大的那个值,并显示 这里给出一个例子 IF (OBJECT_ID('tempdb..# ...

  5. SQL Server表分区的NULL值问题

    SQL Server表分区的NULL值问题 SQL Server表分区只支持range分区这一种类型,但是本人觉得已经够用了 虽然MySQL支持四种分区类型:RANGE分区.LIST分区.HASH分区 ...

  6. [转载]在SQL Server 中,如何实现DBF文件和SQL Server表之间的导入或者导出?

    原来使用SQL Server 2000数据库,通过DTS工具很方便地在SQL Server和DBF文件之间进行数据的导入和导出,现在安装了SQL Server2005之后,发现其提供的“SQL Ser ...

  7. SQL server 表中如何创建索引?

    SQL server 表中如何创建索引?看个示例,你就会了 use master goif db_id(N'zhangxu')is not nulldrop database zhangxugocre ...

  8. SQL Server表分区【转】

    转自:http://www.cnblogs.com/knowledgesea/p/3696912.html SQL Server表分区   什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在 ...

  9. SQL SERVER表不能修改表结构的处理方法

    SQL SERVER表提示不能修改表结构,这究竟是什么原因呢?下面就为您介绍处理该问题的方法,如果您在SQL SERVER表修改方面遇到过问题,不妨一看. 新装的SQL SERVER 2008,打开原 ...

随机推荐

  1. golang的传值调用和传引用调用

    传值还是传引用 调用函数时, 传入的参数的 传值 还是 传引用, 几乎是每种编程语言都会关注的问题. 最近在使用 golang 的时候, 由于 传值 和 传引用 的方式没有弄清楚, 导致了 BUG. ...

  2. centos7安装mariadb(mysql)

    centos7 默认可以yum -y install mariadb-server mariadb mariadb-client mariadb-devel 如果出现错误 GPG key retrie ...

  3. LR、SVM、RF、GBDT、XGBoost和LightGbm比较

    正则化 L1范数 蓝色的是范数的解空间,红色的是损失函数的解空间.L2范数和损失函数的交点处一般在坐标轴上,会使\(\beta=0\),当然并不一定保证交于坐标轴,但是通过实验发现大部分可以得到稀疏解 ...

  4. Rolling Update【转】

    滚动更新是一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新.滚动更新的最大的好处是零停机,整个更新过程始终有副本在运行,从而保证了业务的连续性. 下面我们部署三副本应用,初始镜 ...

  5. Day6 - D - Tree 园丁的烦恼 HYSBZ - 1935

    很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题, ...

  6. 036、Java中三目运算符的使用

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  7. 013.Delphi插件之QPlugins,模块化代码示例

    这个DEMO的是一个定义了一个窗体插件接口,把其他窗口注册到这个窗体插件接口中.主程序运行起来,就遍历一下窗体插件接口,把每个窗体内嵌到对话框中 运行效果如下 主窗口代码如下 unit Frm_Mai ...

  8. Scala 线性化规则和 super 操作

    如果一个类有多个父类,且父类的有相同的函数 f,在子类和父类中调用 super.f 都是按从右到左的调用函数的顺序. 这个规则名为:Linearization Rules 如下的代码 trait Ba ...

  9. 学生选课数据库MySQL语句练习题45道

    1. 查询Student表中的所有记录的Sname.Ssex和Class列. select Sname,Ssex,Class from Student;2. 查询教师所有的单位即不重复的Depart列 ...

  10. 吴裕雄--天生自然java开发常用类库学习笔记:LinkedList类

    import java.util.LinkedList ; public class LinkedListDemo01{ public static void main(String args[]){ ...