SQL数据库中临时表、临时变量和WITH AS关键词创建“临时表”的区别
原文链接:https://www.cnblogs.com/zhaowei303/articles/4204805.html
SQL数据库中数据处理时,有时候需要建立临时表,将查询后的结果集放到临时表中,然后在针对这个数据进行操作。
创建“临时表”(逻辑上的临时表,可能不一定是数据库的)的方法有一下几种:
1.with tempTableName as方法(05之后出现):
with temptable as 其实并没有建立临时表,只是子查询部分(subquery factoring),定义一个SQL片断,该SQL片断会被整个SQL语句所用到。有的时候,是为了让SQL语句的可读性更高些,也有可能是在UNION ALL的不同部分,作为提供数据的部分。特别对于UNION ALL比较有用。因为UNION ALL的每个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,所以可以使用WITH AS短语,则只要执行一遍即可。
示例:


with Snd
as
(
select * from category
where cgtype=2
and parentid=@FstCgid
),
thrd
as
(
select c.* from category c
inner join Snd s
on c.parentid=s.cgid
and c.cgtype=3
),
forth
as
(
select c.* from category c
inner join thrd t
on c.parentid=t.cgid
and c.cgtype=4
)


注意:上述代码,要是在with Snd前面加一句 “decalare @FstCgid int =1234”,必须以“;”结尾,否则会报错;
备注:如果WITH AS短语所定义的表名被调用两次以上,则优化器会自动将WITH AS短语所获取的数据放入一个TEMP表里,如果只是被调用一次,则不会。而提示materialize则是强制将WITH AS短语里的数据放入一个全局临时表里。
2.临时表方法
临时表与永久表相似,只是它的创建是在Tempdb中,它只有在一个数据库连接结束后或者由SQL命令DROP掉,才会消失,否则就会一直存在(临时表一般被创建后,如果在执行的时候,没有通过DROP Table的操作,第二次就不能再被创建)。临时表在创建的时候都会产生SQL Server的系统日志,虽它们在Tempdb中体现,是分配在内存中的,它们也支持物理的磁盘,但用户在指定的磁盘里看不到文件。
临时表分为本地和全局两种,本地临时表的名称都是以“#”为前缀,只有在本地当前的用户连接中才是可见的,当用户从实例断开连接时被删除。全局临时表的名称都是以“##”为前缀,创建后对任何用户都是可见的,当所有引用该表的用户断开连接时被删除。
示例:


if object_id('tempdb..#tempCategory') is not null drop table #tempCategory
create table #tempCategory(
num int,
CGName varchar(50),
CGID int,
PartnerID int,
UpdTime datetime,
Operator varchar(50)
)


备注:临时表的一些特性:
1)添加、修改、删除列。例如,列的名称、长度、数据类型、精度、小数位数以及为空性均可进行修改,只是有一些限制而已。
2)可添加或删除主键和外键约束。
3)可添加或删除 UNIQUE 和 CHECK 约束及 DEFAULT 定义(对象)。
4)可使用 IDENTITY 或 ROWGUIDCOL 属性添加或删除标识符列。虽然 ROWGUIDCOL 属性也可添加至现有列或从现有列删除,但是任何时候在表中只能有一列可具有该属性。
5)表及表中所选定的列已注册为全文索引。
3.表变量方法
表变量创建的语法类似于临时表,区别就在于创建的时候,必须要为之命名。表变量是变量的一种,表变量也分为本地及全局的两种,本地表变量的名称都是以“@”为前缀,只有在本地当前的用户连接中才可以访问。全局的表变量的名称都是以“@@”为前缀,一般都是系统的全局变量,像我们常用到的,如@@Error代表错误的号,@@RowCount代表影响的行数。
示例:


DECLARE @News Table
(
News_id int NOT NULL,
NewsTitle varchar(100),
NewsContent varchar(2000),
NewsDateTime datetime
)


上述三种方法的区别:
临时表和表变量的区别:
1)表变量是存储在内存中的,当用户在访问表变量的时候,SQL Server是不产生日志的,而在临时表中是产生日志的;
2)在表变量中,是不允许有非聚集索引的;
3)表变量是不允许有DEFAULT默认值,也不允许有约束;
4)临时表上的统计信息是健全而可靠的,但是表变量上的统计信息是不可靠的;
5)临时表中是有锁的机制,而表变量中就没有锁的机制。
临时表和表变量的选择:
1)使用表变量主要需要考虑的就是应用程序对内存的压力,如果代码的运行实例很多,就要特别注意内存变量对内存的消耗。我们对于较小的数据或者是通过计算出来的推荐使用表变量。如果数据的结果比较大,在代码中用于临时计算,在选取的时候没有什么分组的聚合,就可以考虑使用表变量。
2)一般对于大的数据结果,或者因为统计出来的数据为了便于更好的优化,我们就推荐使用临时表,同时还可以创建索引,由于临时表是存放在Tempdb中,一般默认分配的空间很少,需要对tempdb进行调优,增大其存储的空间。
CTE和WITH AS短语结合使用提高SQL查询性能:
cet要比表变量效率高得多!
表变量实际上使用了临时表,从而增加了额外的I/O开销,因此,表变量的方式并不太适合数据量大且频繁查询的情况。
注:存储过程中局部临时表是事务级的如下图:
图片1
图片2:
图1的写法 A和B属于两个不同的事务,所以会报错。而图2的写法是一个事务里面则成功执行。
2. 其他写法就是不用拼接SQL语句,直接写就行
select * into #TempProducts from [dbo].[Sys_Product];
select * from #TempProducts;
3. 一个#号的临时表是事务级别的,就是说一个临时表只存在于一个事务里面。
SQL数据库中临时表、临时变量和WITH AS关键词创建“临时表”的区别的更多相关文章
- 在SQL存储过程中给条件变量加上单引号
在SQL存储过程中给条件变量加上单引号,不加语句就会出问题,以下就是在存储过程中将条件where设置成了动态变化的,给where赋完值再和前面的语句拼接,再execute(SQL) ), )), )+ ...
- Android - 数据存储 -在SQL数据库中保存数据
对于重复的或结构化的数据,保存到数据库中是很好的选择,比如联系人信息.这里假设你对SQL数据库大体上了解然后帮助你学习Android上的SQLite数据库.在Android数据库上需要用到的API可以 ...
- Android学习笔记——保存数据到SQL数据库中(Saving Data in SQL Databases)
知识点: 1.使用SQL Helper创建数据库 2.数据的增删查改(PRDU:Put.Read.Delete.Update) 背景知识: 上篇文章学习了保存文件,今天学习的是保存数据到SQL数据库中 ...
- 分布式SQL数据库中部分索引的好处
在优锐课的java学习分享中,探讨了分布式SQL数据库中部分索引的优势,并探讨了性能测试,结果等. 如果使用局部索引而不是常规索引,则在可为空的列上(其中只有一小部分行的该列不具有空值),然后可以大大 ...
- sql 语句中定义的变量不能和 sql关键字冲突
sql 语句中定义的变量不能和 sql关键字冲突 from bs_email_account account LEFT JOIN bs_group_info gp ON account.group_i ...
- SQL语句:把Excel文件中数据导入SQL数据库中的方法
1.从Excel文件中,导入数据到SQL数据库情况一.如果接受数据导入的表不存在 select * into jd$ from OPENROWSET('MICROSOFT.JET.OLEDB.4.0' ...
- Oracle数据库中SYS、SYSTEM、DBSNMP、SYSMAN四用户的区别
[转] SYS.SYSTEM.DBSNMP. Oracle 数据库中 SYS.SYSTEM.DBSNMP.SYSMAN 四用户的区别 用户: SYS 用户: SYS,默认密码为 CHANGE_ON ...
- 在sql语句中添加php变量
在sql语句中使用{}将php变量扩起来,php就会解析{}中的内容. //案件统计 function getCount($dsql,$tableName,$year){ //诉讼案件总数,总金额 $ ...
- linq中的临时变量
有一个字符串数组: string[]arrStr={"123","234","345","456"}; 现在想得到该数组 ...
随机推荐
- vmware-hostd.exe 占用443端口导致Apache无法正常启动?
问题: [Apache] Problem detected!16:23:19 [Apache] Port 443 in use by ""D:\vmware\VMware W ...
- src引入js时添加时间戳参数方法
代码如下: <script>document.write('<script src="js/judgeLogin.js?t=' + new Date().getTime() ...
- Scala学习笔记(五):内建控制循环
前言 Scala中内建控制循环包括if.while.for.try.match和函数调用. if和while与java类似,不做介绍. for 基础用法 def main(args: Array[St ...
- [JS] ECMAScript 6 - Object : compare with c#
Ref: 对象的扩展 Outline: 属性的简洁表示法 属性名表达式 方法的 name 属性 Object.is() Object.assign() 属性的可枚举性和遍历 Object.getOwn ...
- ALTER SEQUENCE 导致 REPLICAT 延时
1.查看OGG线程状态 GGSCI (klcoredb-node1) 46> info all Program Status Group Lag at Chkpt Time Since Chkp ...
- openresty的安装和使用
1,简介 OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web 平台,是一个强大的 Web 应用服务器,在性能方面,OpenResty可以 快速构造出足以 ...
- react-snippets
rcjc class componentName extends Component { render() { return ( <div> </div> ); } } con ...
- Python2.7编译失败 Failed to build these modules:_curses_panel _hashlib _ssl
1:*** WARNING: renaming "_ssl" since importing it failed: libssl.so.1.0.0: cannot open sha ...
- 洛谷P1434 滑雪【记忆化搜索】
题目:https://www.luogu.org/problemnew/show/P1434 题意: 给一个矩阵,矩阵中的数字代表海拔高度. 现在要找一条最长路径,使得路径上的海拔是递减的. 思路: ...
- 洛谷 P1090合并果子【贪心】【优先队列】
题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可 ...