Sql server 表表达式
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 表表达式的更多相关文章
- SQL Server 表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数
概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...
- SQL Server 表变量和临时表的区别
SQL Server 表变量和临时表的区别 一.表变量 表变量在SQL Server 2000中首次被引入.表变量的具体定义包括列定义,列名,数据类型和约束.而在表变量中可以使用的约束包括主键约束,唯 ...
- 09Microsoft SQL Server 表数据插入,更新,删除
Microsoft SQL Server 表数据插入,更新,删除 向表中插入数据 INSERT INTO insert into tb1 values(0004,'张凤凤') insert into ...
- 在一个SQL Server表中的多个列找出最大值
在一个SQL Server表中一行的多个列找出最大值 有时候我们需要从多个相同的列里(这些列的数据类型相同)找出最大的那个值,并显示 这里给出一个例子 IF (OBJECT_ID('tempdb..# ...
- SQL Server表分区的NULL值问题
SQL Server表分区的NULL值问题 SQL Server表分区只支持range分区这一种类型,但是本人觉得已经够用了 虽然MySQL支持四种分区类型:RANGE分区.LIST分区.HASH分区 ...
- [转载]在SQL Server 中,如何实现DBF文件和SQL Server表之间的导入或者导出?
原来使用SQL Server 2000数据库,通过DTS工具很方便地在SQL Server和DBF文件之间进行数据的导入和导出,现在安装了SQL Server2005之后,发现其提供的“SQL Ser ...
- SQL server 表中如何创建索引?
SQL server 表中如何创建索引?看个示例,你就会了 use master goif db_id(N'zhangxu')is not nulldrop database zhangxugocre ...
- SQL Server表分区【转】
转自:http://www.cnblogs.com/knowledgesea/p/3696912.html SQL Server表分区 什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在 ...
- SQL SERVER表不能修改表结构的处理方法
SQL SERVER表提示不能修改表结构,这究竟是什么原因呢?下面就为您介绍处理该问题的方法,如果您在SQL SERVER表修改方面遇到过问题,不妨一看. 新装的SQL SERVER 2008,打开原 ...
随机推荐
- Regression 回归——多项式回归
回归是指拟合函数的模型.图像等.与分类不同,回归一般是在函数可微的情况下进行的.因为分类它就那么几类,如果把类别看做函数值的话,分类的函数值是离散的,而回归的函数值通常是连续且可微的.所以回归可以通过 ...
- 移动端web(1)
引入 <meta name="viewport" content="wcodeth=device-wcodeth, initial-scale=1, ...
- 第一个Vue.js案例
第一个Vue.js案例 使用Vue有如下几步 引入文件头 加入数据输出框 创建Vue对象,定义数据 案例: <!DOCTYPE html> <html lang="en&q ...
- 关于导出Excel表中存在部门或用户数据权限问题
/** * 导出Controller */ @RequiresPermissions("xxx:weeklightlimit:download") @RequestMapping( ...
- JS开发常用工具函数
1.isStatic:检测数据是不是除了symbol外的原始数据 function isStatic(value) { return ( typeof value === 'string' || ty ...
- 密码学概述&置换密码
密码学 概述 如何将信息进行加密,传送到接收方,接收方在进行解密获取信息,中间即使有窃听者窃听到信息也可解密破解. 密码学分类 密码编辑学(保密) 密码分析学(破译) 该破译与传统的黑客技术有一定的区 ...
- 让SVG以组件的方式引入吧!
安装 npm i -D vue-svg-loader or yarn add -D vue-svg-loader webpack 配置 module.exports = { module: { rul ...
- Andorid 搭建 Linux服务器(一)
00.搭建环境 电脑系统:MacOS下Win7虚拟机 手机型号:红米Note5A 手机系统:MIUI10开发版 软件: SuperSU --通过recovery刷入,管理ROOT权限 Bus ...
- Apache http 包中的常量
org.apache.* org.apache.http.Consts public static final int CR 13 public static final int HT 9 publi ...
- (最详细)JAVA如何连接虚拟机的HBASE和hadoop(JAVA如何远程访问虚拟机HBASE)
第一步: 首先把虚拟机和你的主机(本地电脑)弄通这样本地机器才能访问虚拟机里面的内容 我用的虚拟机为 VMware Workstation linux 为 centeros 补充一点虚拟机设置 1 ...