SQL概述
用户利用SQL命令与关系型数据库进行交互时发生的事情,当用户与数据库建立会话时,会话就被创建了。用Connect user@database 命令可以申请连接数据库,用Disconnect命令可以断开连接
数据定义语言(DDL)
用于创建和重构数据库对象,比如创建(create table/Index/view)、修改(alter table/index/view)和删除(drop table/index/view)表
数据操作语言(DML)
用于操作关系型数据库对象内部的数据,基本命令插入(Insert)、更新(Update)和删除(Delete)
数据查询语句(DQL)
是现代关系型数据库用户最关注的部分,就一个命令查询(Select)
数据控制语言(DCL)
用于控制对数据库里数据的访问,通常用于创建与用户访问相关的对象,以及控制用户的权限,如修改密码(Alter password)、权限(Grant)
数据管理命令
用于对数据库里的操作进行审计和分析,还有助于分析系统性能,如Start/Stop audit
事务控制命令
用于管理数据库事务,如Commit(保存数据库事务)、RollBack(撤销数据库事务)、SavePoint(在一组事务里创建标记点以用于回退)和Set Transaction(设置事务的名称)
SQL最基本的数据类型是字符串类型、数值类型和日期时间类型三大类。但具体如下
定长字符串
具有相同的长度,通常使用空格来填充数量不足的字符
变长字符串
具有长度不固定的字符串,将采用实际长度以节约空间
大对象类型
保存大数据集(比如图像、MP3等),常用的有BLOB和Text数据类型
数值类型
保存在定义为某种数值类型的字段里,常见标准:bit(n)、Bit VarYing(n)、Decimal(P,S)、Integer、smallint、bigint、float(p,s)、double precision(P,s)、real(s)
小数类型
只包含小数点,一般p表示有效位数,S表示小数位数,若位数多,则进行四舍五入
整数类型
不包含小数点的数值,包括正数、负数以及零
浮点数类型
有效位数和标度都可变并且没有限制的小数数值,任何有效位数和标度都可以的
日期和时间类型
用于保存日期和时间的信息,如Date\Time\dateTime\TimeStamp
去除数据库里冗余数据的过程,在设计和重新设计数据库时使用
设计数据库应考虑与用户相关的因素
数据库里应该保存什么数据
用户如何访问数据库
用户需要什么权限
数据库里的数据如何分组
哪些数据最经常被访问
全部数据与数据库如何关联
采取什么措施保证数据的正确性
采取什么措施减少数据冗余
采取什么措施让负责维护数据的用户更易于使用数据库
规格化的方式:采用范式设计
规格化的优点
更好的数据库整体组织性
减少冗余数据
数据库内部的数据一致性
更灵活的数据库设计
更好的处理数据库安全
加强引用整体性的概念
规格化的缺点:降低数据库性能,需要更多的CPU、内存和IO来处理
规格化设计平衡点:一般是处理规格化和去规格化之间的平衡,当设计规格化时,考虑规格化到什么程度,才既保证数据规范化,又可以保证去规格化
表通常具有包含唯一标识表中每一行的一列或一组列,该列或组列称为主键(PK),用于强制表的实体完整性。主键约束注意点:
若未表定义了主键,数据库引擎将通过为主键自动创建唯一索引来强制数据的唯一性。当在查询中使用主键时,索引还允许对数据进行快速访问。
一个表只能包含一个主键约束
主键不能超过16列且总密钥长度不能超过900个字节
由主键约束生成的索引不会使表中的索引数超过999个非聚集索引和1个聚集索引
在主键约束中的主键列必须定义不为Null
若在CLR用户定义类型的列中定义主键,则该类型必须实现支持二进制排序
外键是用于在两个表中的数据之间建立和加强链接的一列或多列的组合,可控制科在外键表中存储的数据。
数据库里定义的、用于存储或引用数据的对象,如表、视图、簇、序列、索引和异名
与数据库某个用户名相关联的数据库对象集合,相应的用户名被称为规划所有人,或是关联对象组的所有人,数据库里可以有一个或多个规划,用户只与同名规划相关联,即就像程序中的命名空间概念类似,所以在数据库里不同的规划中可以有名称相同的表
示范:数据库中两个用户:User1(Test表、table1表、table2表)和User2(Test表、Table10表、table20表)
User1访问自己的table1表:table1
User1访问自己的Test表:Test
User1访问User2的Table10表:User2.Table10
User1访问User2的Test表:User2.Test
创建数据库
语法:Create datebase database-name
删除数据库
语法:Drop database dbname
初始化表
Truncate table tablename
备份数据库
创建备份数据Device:User master Exec sp_addumpdevice ’disk’,’testBack’,’备份路径地址’
开始备份:BackUp database pubs To testBack
创建表时,需要考虑的方面:
表里包含什么类型的数据
表名称是什么
哪个或哪些列组成主键
列的名词时什么
每一列的数据类型是什么
每一列的长度是什么
表里哪些可以是NULL
创建表
语法一:Create Table table_name
( Col1 data_type [not null] [primary key],
Col2 data_type [not null] [primary key],
);
此语法是创建一张新的表,一般最后都要带分号,但是不同的数据库稍微有点区别
语法二:Create Table newtable_name like tab_oldname 完全复制
Create Table newtable_name as
select [col1,col2,…] from oldtable_name [where]
此语法是从现有表新建另外一个表,且MySQL和Oracle都支持As select语法,但MSSQLServer则使用如下语法:
Select [col1,col2,…] into newtable_name
From oldtable_name [where]
删除表
语法:Drop Table table_name [restrict|cascade]
若使用restrict选项,并且表被视图或约束所引用,则会引发一个错误
若使用cascade选项,删除操作会成功执行,且全部引用视图和约束都会被删除
视图是一个虚拟表,对于用户来说,视图在外观和行为上都类似表,但它不需要实际的物理存储,且视图可以包含表的全部或部分记录,可以由一个表或多个表创建,它和表示一样的,所以可以像操纵表一样从视图获取数据。
表与视图的主要区别在于表包含实际的数据、占据物理存储空间,而视图不包含数据,且只需要保存视图定义。
通过视图更新数据
在一定条件下,视图底层的数据可以进行更新
视图不包含结合
视图不包含Group by子句
视图不包含Union语句
视图不包含对伪字段RowNum的任何引用
视图不包含任何组函数
不能使用Distinct子句
Where子句包含的嵌套的表达式不能与From子句引用同一个表
视图可以执行Insert、Update和Delete等语句
l 创建视图
从一个表创建视图语法:Create View view_name as
Select *|col1,col2,..
From table_name
[where conditions][with check option][group by]
从多个表创建视图语法:Create View view_name as
Select *|col1,col2,..
From table1_name,table2_name,…
Where table1_name=table2_name [with check option][group by]
从视图创建视图语法:Create View2 As Select * From View1
从视图创建表语法:Create Table table_name As
Select *|col1,col2,…
From View_name [Where condition] [Order by]
删除视图
语法:Drop View view_name [Restrict|Cascade]
语法解析:若使用Restrict选项,其他视图在约束力有所引用,删除操作就会出错;若使用Cascade,其他视图或约束被引用,一样会成功。
索引就是一个指针,指向表里的数据的准确物理位置,当数据库表没有索引时,通常进行的操作都叫全表扫描,就如书籍中的索引类似功能
索引的特点
索引通常与相应的表分开保存,索引似乎以一种树形结构保存信息,主要是提高数据的检索性能
当表里添加新数据时,索引里也会添加新项
当执行查询的时候,且where条件指定的字段设置了索引,则首先在索引里找符合要求的数据
索引创建于删除不会影响到数据本身,但会影响数据检索的速度
索引页会占据物理存储空间,且可能会比表本身还大
索引使用场景
一般来说大多数用于表结合的字段都应该设置索引
经常在Order By和Group by 里引用的字段也应该考虑设置索引
具有大量唯一值的字段,或是在where子句里会返回很小部分记录的字段可以考虑使用索引
避免使用索引场景
索引不英爱用于小规模的表
当字段用于where子句作为过滤器会返回表里的大部分记录时,该字段就不适合设置索引
经常会被批量更新的表可以具有索引,但批量操作的性能会由于索引而降低
不应该对包含大量NULL值得字段设置索引
经常被操作的字段不应该设置索引,因为对索引的维护会变得繁重
常被作为索引的数据
作为主键的字段
作为外键的字段
在结合表里经常使用的字段
经常在查询里作为条件的字段
大部分值是唯一值得字段
创建索引
单字段索引语法:Create Index index_name On table_name(col1)
唯一索引语法:Create Unique Index index_name On table_name(col1)
组合索引语法:Create Index index_name On table_name(col1,col2,..)
语法解析
一般创建表的主键后,都会默认创建一个默认的主键索引,所以通常不设置主键为索引
当创建组合索引时,必须考虑字段在索引的次序,会影响数据检索数据的速度,一般最具有限制的字段应该排在前面
选择单索引还是组合索引的方法:若经常只使用一个字段,就选择单索引;若经常使用两个或多个字段,就选择组合索引
l 删除索引
语法:Drop Index index_name
MySQL语法:Drop Index index_name on table_name
用于确定关系型数据库里数据的准确性和一致性
主键约束
表示表里一个或多个用于实现记录唯一性的字段,主键可以是一个列或多个列共同组成,在创建表时创建主键
多个列名组合语法:Create Table table_name
( Col1 data_type [not null] ,
Col2 data_type [not null],
Col3 data_type [not null]
Primary key(col1,col2));
删除主键:Alter Table table_name Drop Constraint Primary key(colname)
唯一性约束
要求表里某个字段的值在每条记录里面都是唯一的,与主键类似,区别是主键是让表有了一定的次序且可以结合相互关联的表
语法:Create Table table_name
( Col1 data_type [not null] ,
Col2 data_type [not null],
Col3 data_type [not null] Unique,
Primary key(col1,col2));
外键约束
是子表里的一个字段,引用父表里的主键,确保表与表之间引用完整性的主要机制
语法:Create Table table_name
( Col1 data_type [not null] ,
Col2 data_type [not null],
Col3 data_type [not null] Unique,
Primary key(col1,col2)
Constraint constraint_name Foreign key (Col3) References table2_name(Col3));
检查约束
用于检查输入到特定字段的数据的有效性,可以提供后端的数据库编辑
语法:Create Table table_name
( Col1 data_type [not null] ,
Col2 data_type [not null],
Col3 data_type [not null] Unique,
Primary key(col1,col2),
Constraint contstraint_name Check(col1=’0001’));
上述添加一个约束检查用于所有Col1代码都是0001的约束
把单独数据插入到表
语法:Insert Into table_name [(col1,col2,..)]
Values(value1,value2,..)
语法解析
在values列表中如果是字符、日期和时间数据类型的值必须以单引号标记(‘value1’),而数值或null就不需要了
也可以动态指定插入的列名,且table_name [(col1,col2,..)]中的列名不一定要跟表中的列名顺序一致,但table_name [(col1,col2,..)]和Values(value1,value2,..)中的顺序和类型必须保持一致
当插入null值得时候必须保证所插入的列允许为null
插入数据时,若遗漏列表和数值表中的一列,那么当该列存在默认值,则使用默认值,若不存在默认值,则使用NULL
l 从另一个表中查询数据插入到表
语法: Insert Into table_name [(col1,col2,..)]
Select [*|(col1,col2,…)]
From table_name [where conditions]
Eg:Insert into NewTable(Id,name,age) select Id,name,age from Teacher
语法解析
必须保证查询返回的字段与要插入列表的字段具有相同的次序和数据类型或是兼容类型
比使用多个单行的Insert…values语句效率高得多
必须检验要插入新的行的表是否存在
必须保证是否存在默认值,或被忽略的列是否允许为空
可以把任何查询结果集放置到一个新表中
语法:Select select-list into new_tablename
From table_list
Where search_condition
Eg: select Id,name,age into #A from student
语法解析
创建一个表且单独操作向表中插入行,确定表select into语句中表名是唯一的,若非唯一,将失败
可以创建本地货全局临时表,本地:#,全局:##
当使用者结束会话时,本地临时表空间会被回收
当创建表的会话结束且当前参照表的最后一个SQL语句完成时,全局临时表空间会被回收
修改表或视图里的现有数据,不向表或视图里添加新纪录,也不删除数据,只是修改现有数据,每次只更新一个表或视图,但可以同时更新表或视图中多个字段
根据表或视图中数据更新一列或多列数据
语法: Update [top] table_name_or_view_name
Set col1_name=value1,col2_name=value2,…
[where conditions]
Eg: update teacher set age=age+1
update teacher set age=age+1 where '12'=(select Id from student)
语法解析
用where子句指定更新的行,用Set指定新值,且set只能出现一次
Update无法更新标识列
不会更新任何违反完整性约束的行,如行的更新违反约束或规则,则取消该语句,并返回错误提示,不会更新任何记录
若子查询没有返回值,必须在子查询中引入In,Exists
可以考虑在相关子查询中使用聚合函数
删除只删除行的数据且是行全部数据,不删除列的数据,且一般要带上where语法,否则会删除所有数据
语法:Delete From table_name_or_view_name [where conditions]
数据查询中主要是Select语句的使用,使用它对数据库数据进行探究。
可以从数据库中按照用户的要求检索数据,并以查询结果以表格的形式输出数据,结果集采用表的形式,结果集也由行和列组成。Select语句是一个查询表达式,包括Select、from、where、groupby、order by子句,具有数据查询、统计、分组和排序功能
Select语句执行顺序
From子句---where子句----group by子句-----Having子句----Select子句---Order by子句
语法
Select [All/Distinct] select-list
[Into new-table] 查询结果
From table-Source 查询来源
[Where search-conditions] 查询表达式
[Group by group-by-expression] 按照表达式分组
[Having search-conditions] 只有满足条件才可以
[order by orderby expression Asc/Desc] 进行升/降排序
语法解析:
Distinct关键字:去除查询结果中的重复集,可以和count函数一起使用查询种类数量
Eg:select count(distinct *) from db_owner
Top关键字:表示结果集的前N项集合
Eg: select top 10 * from db_owner
使用别名:采用符合ASCII规则的标准方法
Eg:select ID '编号',name ‘名字’from db_owner
采用=连接表达式
Eg:select ID ='编号',name =‘名字’from db_owner
采用As关键字表达式
Eg:select ID as '编号',name as ‘名字’from db_owner
后面可以跟着表达式,用于计算列
Eg:select ID,Code-15 as ‘调整后的成绩’from db_owner
查询来源多个表的,可以用逗号隔开,相应的.运算符
Eg:select ID,Code-15 as ‘调整后的成绩’from db_owner,db_accessadmin
Where使用条件
比较运算符:= 、>、 <、 >=、 <=、 <>、 !=
Eg:查询性别为女的学生的信息
select * from studet where sex='女'
Eg:查询性别为女,政治面貌为党员的信息
select * from studet where sex='女' and ZZMM=‘党员’
连接操作符优先级高到低:Not And OR
And表示所有and连接的都必须为True,才会实际执行
Or表示连接条件中至少有一个是True,才会实际执行
范围运算符:Between 、Not Between
Eg:查询学号在201307121-201307131之间的信息
select * from student where studentID between 201307121 and 201307131
列表运算符:In 、Not In
Eg:查询学号为1,2,3所有学生信息
select * from student where studentId In('1','2','3')
字符匹配符:Like、Not Like
通配符百分号(%)表示零个、一个或多个字符;下划线(_)表示一个数字或字符
Eg:select * from student where studentId like '_10%'
未知值:Is null、Is Not NULL
Eg:查询学号为空的学生信息
select * from student where studentId Is Null
存在运算符:Exists、Not Exists
Eg:查询表里价格超过100的所有记录
Select cost from products_tbl where exists(select cost from products_tbl where cost >100)
满足运算符:All、Some、Any
All用于把一个值与另一个集合里的全部值进行比较
Eg:价格大于那些价格小于10的所有记录
Select * from products_tbl where cost>All(select cost from products_tbl where cost<10)
Any和Some用于把一个值与另一个列表里的任意值进行比较
Eg:价格比小于10的价格中的任何一个高即可
Select * from products_tbl where cost>Any(select cost from products_tbl where cost<10)
将结果集按照某列或多列进行分类、分组
语法:Select col1_name,col2_name,..
From table1_name,table2_name,….
Where conditions
Group by col1_name,…
Order by col1_name,….
Eg:select * from student group by ClassId
语法解析
该子句对CPU的运行效率有很大影响,若不对提供给它的数据进行约束,那么后期很可能需要删除大量的无用的数据。
通常情况会该子句中的列序对返回结果进行排序。
用于限定分组统计值,一般与Group By一起用,注意:
若指定group by子句,则应用于group by创建组
若有where,无group by子句,则应用于where输出结果
若既无where子句,也无group by 子句,应用与from子句
Eg:按照班级编号查询出每个班级选课总数,然后输出课程总数大于10的班级编号和选课总数
select classId,COUNT(CourseName) as 选课总数 from subjecttable group by Classid having COUNT(*)>10
对查询结果按一个或多个列进行升/降排序
Eg:select * from Re_table order by age asc,ID desc
也被称为嵌套查询,是位于另一个查询的where子句里的查询,它返回的数据通常也在主查询里作为一个条件
语法:Select col_name
From Table
Where Col_name=(Select col_name from table where condition)
子查询遵循的规则
子查询必须位于圆括号内
除非主查询里有多个字段让自查询进行比较,否则子查询的Select子句中只能有一个字段
子查询里不能使用Order by子句,可以用Group by替代
返回多条记录的子查询只能与多值操作符(比如In)配合使用
select列表里不能引用任何Blob、Arrary等类型的值
子查询不能直接被包围在函数里
操作符Between不能用于子查询,但子查询中可以用它
子查询的效率
在应用子查询钱,必须首先考虑好奇所带来的影响,由于子查询会在主查询之前进行,所以子查询所花费的时间,会直接影响整个查询所需要的时间
通过各个表之间的共同列的相关性来查询数据,主要包含四种类型:等值结合(内部结合)、非等值结合、外部结合、自结合等
在连接条件中使用比较运算符(=)来比较连接列的列值,其查询结果中列出被连接表中所有列,且包括重复列
语法一:Select select-list
From table1 [Inner] join table2 On table1.A=table2.A [order by order_condition]
语法解析
内连接有返回信息条件是当且仅当至少有一个同属两个表的行符合连接条件
内连接从第一个表中消除与另一个表中任何不匹配的行
语法二:Select select-list
From table1 ,table2
Where table1.A=table2.A
Eg:select R.ID,R.name,M.soce FROM R INNER JOIN M on R.Id=M.Id
又名同链接,一个基表中的一个或多个列值与第二个表中对应的一个或多个列值相等的连接
在连接条件中使用除等号之外的比较运算符的连接列值连接,即根据同一个字段在两个表里值不相等来实现
语法:Select select-list
From table1 ,table2
Where table1.A<>table2.A
组合查询由负责结合两个查询的操作符组成
使用注意
Order by 可以用于组合查询,但它智能用于对全部查询结果的排序,所以组合查询中只能有一个Order by
在组合查询中一般是以数字形式,表示排序的列名,如Order by 1
Group by 子句可以用于组合查询中的每一个Select语句,也可以用于全部查询结果
Having子句也可以用于组合查询里面的每个Select语句
将多个不同的查询结果连接在一起组成一组数据的查询方式,可以使用Union关键字连接各Select子句,并取消表中任何重复行
语法:Select select-list
From table_name
[where search_condition]
Union [All]
Select select-list
From table_name
[where search_condition]
[order by oderby_expression]
语法解析
使用Union应保证每个联合查询的选择列表中具有相同数量的表达式,且每个查询选择表达或应具有相同数据类型
如果使用Union All,则组合结果中包含重复行
组合两个Select语句,返回第一个Select语句里有但第二个Select语句中没有的记录,并消除所有重复行(除了Except All外)
语法:Select select-list
From table_name
[where search_condition]
Union [All]
Select select-list
From table_name
[where search_condition]
[order by oderby_expression]
组合连个Select,但只返回第一个Select语句里与第二个Select语句一样的记录,并消除重复行(除了Intersect All外)
语法:Select select-list
From table_name
[where search_condition]
Intersect [All]
Select select-list
From table_name
[where search_condition]
[order by oderby_expression]
返回一个表里的全部记录,即使对应的记录在第二个表里不存在
语法:Select select-list
From table1 [Right|Left|Full] Outer Join table2 On table1.A=table2.A
[Where condition]
Eg: select S.id,c.ID from S left outer join C on S.Id=C.Id
左外连接(Left outer join)
返回所有匹配行并从关键字Join左边表中返回所有不匹配的行
右外连接(Right outer Join)
返回所有匹配行并从Join右边表中返回所有不匹配行
完全连接(Full outer join)
返回两表中所有匹配行和不匹配行
一个表与自身相互连接的查询,是通过给基表定义别名的方式来实现,它可以用其他查询方式的任何方式
Eg:Select A.Id,B.Name,A.Name from EM_TBL A,EM_TBL B where A.Id=B.Id
生成来自两基表的各行的所有可能组合,结果集中包含两个基表每两个可能成对的行占一行,比如A表中有6条记录,B表中有4条记录,则结果是用A表中每一条记录对应B表中每一条记录生成新的一条记录,所以最终生成6*4=24条组合记录
不使用where子句的交叉连接
结果集被连接的两个基表所有行的笛卡尔积,即返回到结果集中行数=一个基表中符合查询条件的行数*另一个表中符合条件的行数
使用where子句的交叉连接
结果集被连接的两个基表所有行的笛卡尔积,where搜寻的行数
函数是一个命令,通常与字段名称或表达式联合使用,处理输入的数据并产生结果。
汇总函数提供合计信息,如计数、总和、平均等
Count函数:统计不包含Null值de记录或字段值,返回一个数值
语法:Count[(*)|Distinct|All](Col_name)
Eg:Select count(distinct employee_id ) from Employee_Tbl
Sum函数:返回一组记录中某个字段值的总和
语法:Sum([Distinct] Col_name)
所处理的字段类型必须是数值类型的,不能是其他数据类型(字符或日期)
Avg函数:计算一组指定记录的平均值
语法:Avg([Distinct] Col_name)
Max/Min函数:返回记录中某个字段的最大或最小值,Null不在计算范围之内
语法:Max/Min([Distinct] Col_name)
串接函数:将两个或多个字符串接起来,不同的数据库产商有不同的区别
Oracle语法:col_name||col2_name||…
SQL Server语法:col1_name+col2_name+…
MySql语法:Concat(col1_name,col2_name,..)
Translate函数:搜索字符串里的字符并查找特定的字符,标记找到的位置,然后替代字符串里对应的字符替换它
语法:Translate(character set,value1,value2)
Eg:Select city,translate(city,’IND’,’ABC’) from employee_TBL
Replace函数:用于把某个字符或字符串替换为指定的一个字符或多个字符
语法:Replace(‘value’,’value’,’value’)
Eg: Select replace(first_name,’T’,’B’) From employee_TBL
Upper/Lower函数:把字符串中的字符进行大小写转换
语法:Upper/Lower(character string)
Substr函数:获取字符串指定字符子串的函数
Oracle语法:Substr(Col_name,start_position,length)
SQL Server语法:SubString(Col_name,start_position,length)
Instr函数:在字符串里寻找指定的字符集,返回其所在的位置
语法:Instr(col_name,’set’,start_position,…)
Ltrim/Rtrim函数:分别从左边或者右边剪除字符串
语法:Ltrim/Rtrim(character string,’Set’)
其他函数:Length(character string)、Ifnull(‘VALUE’,’Substitution’)、数学函数等
产品 |
日期函数 |
用途 |
SQL Server |
Datepart |
返回日期的某个元素的整数值 |
Datename |
返回日期的某个元素的文本值 |
|
GetDate() |
返回系统日期 |
|
DateDiff |
返回两个日期之间由指定日期元素表示间隔 |
|
Oracle |
Next_Dat |
返回指定日期之后的下一天 |
Months_between |
返回两个日期之间相差的月数 |
|
MySQL |
DayName(date) |
显示星期几 |
DayOfMonth(date) |
显示几日 |
|
Dayof Week(date) |
显示星期几 |
|
DayofYear(date) |
显示一年中的第几天 |
SQL语句调整就是优化生成SQL语句的过程,从而以最有效和最高效的方式获得结果。主要涉及调整语句的From和where子句,因为数据库服务程序主要根据这两个子句执行查询。它的目标是利用数据库和系统资源、索引,针对数据库的当前状态进行最有效的访问,从而减少对数据库执行查询所需的开销。
数据库调整是调整实际数据库的过程,包括分配内存、磁盘、CPU、IO和底层数据库进程,还设计数据库结构本身的管理与操作,比如表和索引的设计和布局。它的目标是确保数据库的设计能够最好地满足用户对数据库操作的需要。
提高可读性格式化SQL语句
每个子句都以新行开始
当子句的参数超过一行的长度需要换行时,利用制表符或空格来形成缩进
以一致的方式使用制表符和空格
当语句里面使用多个表时,使用表的别名
如果SQL实现里允许使用注释,应该在语句里有节制地使用
如果Select语句里要使用镀铬字段,就让每个字段都从新行开始
如果From子句里要使用多个表,就让每个表明都从新行开始
让Where子句里每个条件都以新行开始,这样可以清晰地看到语句的所有条件及其次序
虽然提高语句的可读性并不会直接改善它性能,但这样会帮助我们更方便的修改和调整很长和很复杂的语句。
From子句里的表的顺序
From子句里的表的安排活次序对性能有很大影响,取决于优化器如何读取SQL语句,一般把较小的表列在前面,把较大的表列在后面会去的更好的性能。
语法:From small_table, largest_table
结合条件的次序
Where子句中来自基表的字段一般放到结合操作的右侧,要被结合的表通常按照从小到大的次序排序,如果没有基表,那表就应该从小到大排列,让最大的表位于Where子句里结合操作的右侧。
语法:From smallest_table A ,Middle_table B,Largest_table C
Where A.ColID=C.ColID and B.ColID=C.ColID
最严格条件
最严格条件是SQL查询达到最优行性能的关键因素,它是where子句里返回最少记录的条件,因其返回最小的数据子集,从而减小查询的开销。一般是把最严格条件放到where子句的末尾,从而让优化器首先读取它。
使用Like操作符和通配符
避免使用OR操作符:一般使用In代替OR操作符能够提高数据检索的速度。
避免使用Having子句:使用Having是虽然很有用,但是需要付出代价
避免大规模排序操作:排序会影响SQL语句的相应时间
使用存储过程:可以提高性能
在批加载时关闭索引:在批量加载时,索引可能会严重降低性能
“Where 1=1,1=2”, “Where 1=1”表示选择全部 ”where 1=2”表示全部不选
选择从N到M条记录,且N<M,N>0,M<Count
Eg:Select top 5 * from (select top 15 * from table order by id as c) table_name order by desc
包括所有在TableA中但不在TableB和TableC中的行并消除所有重复行而派生出一个结果表
Eg:(select a from tableA ) except (select a from tableB) except (select a from tableC)
随机取记录
Eg:select top 10 * from tablename order by newid() 随机取出10条记录
Select newid() 随机选择记录
列出数据库里所有表名,某张表里的所有列名,查看数据库所有存储过程
Eg:Select name from sysobjects where type=’U’ and status>=0 (U代表用户)
Select name from syscolumns where id=object_id(‘tablename’) 列出列名
Select name as 存储过程名 from sysobjects where xtype=’P’
两张关联表,删除主表中已经在附表中没有的信息
Eg:delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )
日程安排提前五分钟提醒
Eg:select * from 日程安排 where datediff(‘minute’,f开始时间,getdate())>5
选择在每一组B值相同的数据中对应的a最大的记录的所有信息(应用于论坛每月排行榜、每月热销产品分析、科目成绩排名)
Eg:select a,b,c from tablename ta where a=(select max(a) from ta)
按姓氏笔画排序
Eg:select * from tablename order by customername collate c hinese_PRC_Stroke_ci_as