码迷,mamicode.com
首页 > 数据库 > 详细

SQL进阶之select

时间:2016-08-14 10:09:11      阅读:301      评论:0      收藏:0      [点我收藏+]

标签:

1.认识select

  select的主要语法如下,这个很重要因为只有记住了整体的结构才能应对任何情况。从中可以看到select的强大主要就是建立在where、group by、having、order by这4个功能之上。

select [all | distinct] select_list [into new_table]    [from  table_source] 

[where search_condition]

[group by byexpression]      

[having search_condition]

[order by order_expression [asc|desc] ]

再来看这6个关键字的执行顺序,显然首先你得找到表取得最原始最庞大的数据,因此是from。接着是where用来进行过滤,然后group by和having开始执行,这样数据的过滤已经完成所以就是select了,还有一个order by就是最后了。总结起来顺序是from、where、group by、having、select、order by。如果再加上其它功能点,完整的执行顺序为from,on,join,where,group by,having,with rollup或cube,select,distinct,order by,top。关于from要注意当为表使用别名时,一旦使用将不能够再用表名,只能使用as后的别名。where中可以使用很多运算符组合过滤条件,系统过滤数据时将按照过滤条件以行为单位一条条的进行过滤。在运算符中逻辑运算符的优先级为not、and、or,而且not只能用于简单条件式,不能用于包含and和or的复杂条件式。

  group by为我们带来了非常方便的分组功能,但要注意使用时select中只能是by后面的列名和聚集函数。当以by后面的列进行分组时,如果在select中包括其它的列比如columnA,那么系统将不知道显示分组后的columnA集合中的哪一条数据,这就是为什么不能select其它列的原因。另外还要注意group by后的列名必须使用完整的名字,不能出现as的别名,原因很简单就是因为执行顺序。having和where很相似,它们都可以对结果进行过滤。它们的区别则有2点:having中可以包含聚集函数,而where是不允许有聚集函数的;having中出现的列必须是select中存在的,而where则可以使用表中的任意列。

  在查询中,如果要对多表进行查询可使用where或表连接来进行关联。和表连接一样,联合查询也是查询中很有效的手段,当然它和表连接有着本质的区别,使用它有3个要注意的地方。首先union联合的2个select语句,必须要有相同数量的列。在有相同列的情况下,列还必须拥有相似的数据类型,最后select语句的顺序也要相同。它的作用则是将多个select的结果集拼接在一起并一起显示在结果集上,表连接是将表进行关联连接,而联合查询只是联合了查询出来的结果集,将这些结果集放到一起显示而已。使用union会发现它除了去除重复行外,还会对结果集进行一个排序,union all既不会去除重复行也不会对结果进行排序。关于union的用法读者可自己去写sql,这里我要强调的是一个使用union常见的错误,数据表sql语句如下所示。

技术分享
--创建数据库
create database testDb  on
(
name=testDb_data,
filename=D:\testDb_data.mdf,
size=4,
filegrowth=10%
)
log on
(
name=testDb_log,
filename=D:\testDb_data.log,
size=2,
filegrowth=10%
)

--创建student表
use testDb
create table student
(
studentId int primary key,
studentName nvarchar(16) not null,
studentAge int default(18),
studentSex nchar(1)
)

create table teacher
(
teacherId int primary key,
teacherName nvarchar(16) not null,
teachClass nvarchar(16)
)

--为student添加新的一列并添加主外键约束
alter table student add
teacherId int,constraint teacher_FK foreign key(teacherId) references teacher(teacherId)
select * from teacher

insert into teacher values(1,刘老师,安卓)
insert into teacher values(2,吴老师,网站)
insert into teacher values(3,王老师,物联网)

select studentId,studentName  from student 
union all
select teacherId,teacherName from teacher
View Code

技术分享

如果在上面sql中的union后加上order by teacherId则会出现错误,提示上说order by项必须出现在选择列表中,可是这里teacherId明明就是选择列表中的列啊。再仔细看看结果集会发现列上的名字是以第一个select中的列名为标题的,因此这里teacherId还真没有出现选择列表中。将teacerId改为studentId或studentName将会顺利执行,关于结果集读者可自行去试。

select studentId,studentName  from student 
union all
select teacherId,teacherName from teacher 
order by teacherId

技术分享

select studentId,studentName  from student 
union all
select teacherId,teacherName from teacher 
order by studentId,studentName

在错误提示中还出现了intersect和except运算符,既然遇到了那肯定要掌握。这3个运算符一起出现说明它们有着某种紧密的联系。union如前面所说是两个数据集的并集,intersect是两个结果集的交集,except则是两个结果集的差集。以上面的表为例,如果使用intersect结果集将为空,因为这两个集合根本就没有相同的数据集。使用except则返回的是第一个select返回的结果。使用union和except的结果如下所示。

技术分享
select studentId,studentName  from student 
union
select teacherId,teacherName from teacher 
order by studentId,studentName

select studentId,studentName  from student 
except
select teacherId,teacherName from teacher 
order by studentId,studentName
View Code

技术分享         技术分享

2.从select into到临时表

  在实际应用中开发者经常会需要去创建一个临时的表存储数据,select into正是扮演着这样的角色。使用select into要注意创建的表名必须是唯一的,当我们使用select into创建一个临时的表时会在当前数据库中建立一张新表。注意这张表已存在于当前数据库中,这样的话开发者还需要手动drop,如果忘记删除将会导致数据库中的表越来越多,而且很有可能重名。为了改进这一缺点,SQL利用了和C#里的垃圾回收一样的思想,就是由系统来删除临时表,当然我们也可以手动删除。我们只需要在设置临时表名前加上#或##,一个#表示本地临时表,两个#表示全局临时表。对于本地临时表,最重要的特点是创建后只对当前这次会话状态有效,一次会话状态指的是客户端与数据库引擎的连接,这里客户端指登入者在数据库上进行操作的一端,最终执行是需要连接数据库引擎来完成的。比如select * into #table1 from student where studentId<4,执行后在系统数据库中的tempdb可看到创建的临时表。并且它的名字很有意思,sql可能是为了防止重名吧,它还为我们创建的本地临时表又添加了后缀名。当我关掉选项卡后,这个临时表也就从tempdb中消失了,也就是说本地临时表它属于创建它的当前用户,且只在当前会话状态下可使用。全局临时表创建后,所有用户都可见,当创建者介绍这次会话时比如我关掉选项卡,会发现全局临时表和本地临时表一起被删了。那是不是说全局临时表和本地临时表一样,也是当前会话状态结束就被系统删除呢?答案是否定的,这里和GC很像,如果没有其他任务引用这个全局临时表,那它就被删除。但要注意创建着会话状态存在时,其他任务可引用它创建的全局临时表,创建着会话状态存结束时,其他任务将不能再引用这个全局临时表,但是此时如果已有任务引用这个全局临时表不会删除,直至没有任务引用它。另外临时表并不是只有select into可以创建,我们也可以直接使用create table创建。

  创建临时表和非临时表相比,有哪些优点和缺点呢?首先我们最关注的肯定是性能,临时表有一个特点那就是对它的操作不会记录日志文件,而非临时表则会进行记录,因此临时表性能比非临时表更快。在临时表中,由于本地临时表只对当前用户的当前会话状态有效,那么完全不需要对本地临时表进行加锁,所以从这一点来说本地临时表比全局临时表更快。显然这些性能的提高同时伴随着某些功能将无法使用,有利也有弊。临时表与非临时表一样,也可以建立索引、约束,只是不能建立外键约束,对于临时表和非临时表我们都可以使用drop和truncate来删除表。

声明:本文原创发表于博客园,作者为方小白 ,如有错误欢迎指出。本文未经作者许可不许转载,否则视为侵权。

SQL进阶之select

标签:

原文地址:http://www.cnblogs.com/fangyz/p/5757958.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!