1.认识selectsql
select的主要语法以下,这个很重要由于只有记住了总体的结构才能应对任何状况。从中能够看到select的强大主要就是创建在where、group by、having、order by这4个功能之上。数据库
select [all | distinct] select_list [into new_table] [from table_source] express
[where search_condition]ide
[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的复杂条件式。spa
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语句以下所示。code
--建立数据库 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
若是在上面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
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来删除表。