SQL概述
SQL的产生和发展
历史就略了,想了解就百度。目前,没有一个数据库系统能够支持SQL标准的所有概念和特性。许多软件厂商对SQL基本命令集还进行了不同程度的扩充和修改,又可以支持标准以外的一些功能特性。
SQL的特点
-
综合统一
非关系模型(层次模型、网状模型)的数据语言一般都分为:
- 模式数据定义语言(DDL):用于定义模式
- 外模式数据定义语言(外模式DDL或子模式DDL):定义外模式
- 数据存储有关的描述语言(DSDL):定义内模式
- 数据操纵语言(DML):进行数据的存取和处置
SQL集数据定义语言、数据操纵语言、数据控制语言的功能于一体,包括以下一系列操作要求:
- 定义和修改、删除关系模式,定义和删除视图,插入数据,建立数据库。
- 对数据库中的数据进行查询和更新。
- 数据库安全性、完整性控制,以及事务处理。
- 嵌入式SQL和动态SQL定义。
-
高度非过程化
用SQL语言进行数据操作时,只要提出“做什么”而无须指明“怎么做”,减轻了用户负担,有利于提高数据独立性。
-
面向集合的操作方式
操作对象为一条记录,SQL采用集合操作方式,不仅操作对象、查找结果可以是元组的集合,而且一次插入、删除、更新操作的对象也可以是元组的集合。
-
以同一种语法结构提供多种使用方式
SQL既是独立的语言,又是嵌入式语言。用户可以在终端直接键入SQL命令,也可以嵌入到高级语言程序中,语法基本上是一致的,提供了极大的灵活性与方便性。
-
语言简洁,易学易用
核心功能只用了9个动词,如下表:
SQL功能 | 动词 |
---|---|
数据查询 | SELECT |
数据定义 | CREATE,DROP,ALTER |
数据操纵 | INSERT,UPDATE,DELETE |
数据控制 | GRANT,REMOVE |
SQL的基本概念
数据库三级模式结构,其中外模式包括若干视图(View)和部分基本表(base table),数据库模式包括若干基本表,内模式包括若干存储文件(stored file)。下图为SQL对关系数据库模式的支持:
数据定义
SQL的数据定义语句表:
操作对象 | 创建 | 删除 | 修改 |
---|---|---|---|
模式 | CREATE SCHEMA | DROP SCHEMA | |
表 | CREATE TABLE | DROP TABLE | ALTER TABLE |
视图 | CREATE VIEW | DROP VIEW | |
索引 | CREATE INDEX | DROP INDEX | ALTER INDEX |
一个关系数据库管理系统的实例中可以创建多个数据库,一个数据库中可以创建多个模式,一个模式下通常包括多个表、视图和索引等数据库对象。
模式的定义与删除
-
定义模式:模式语句如下:
CREATE SCHEMA<模式名>AUTHORIZATION<用户名>[<表定义子句>|<视图定义子句>|<授权定义子句>];
如果没有指定模式名,那么隐含为用户名。
-
删除模式:模式语句如下:
DROP SCHEMA <模式名>
; 其中CASCADE和RESTRICT两者必选其一。选择CASCADE(级联),表示在删除模式的同时把该模式中所有的数据库对象全部删除;选择RESIRICT(限制),表示如果该模式中已经定义了下属的数据库对象(如表、视图等),则拒绝该删除语句的执行。
基本表的定义、删除与修改
-
定义基本表
CREATE TABLE <表名> (<列名><数据类型>[列级完整性约束条件][,<列名><数据类型>[列级完整性约束条件]]...[,<表级完整性约束条件>]);
例子:建立一个”课程“表Cource
CREATE TABLE Cource (Cno CHAR(4) PRIMARY KEY, /*列级完整性约束条件,Cno是主码*/ Cname CHAR(40) NOT NULL, /*Cname不能取空值*/ Cpo CHAR(4), Credit SMALLINT, FOREIGN KEY (Cpno) REFERENCES Cource (Cno) /*表级完整性约束条件,Cpno是外码,被参照表是Cource,被参照列是Cno*/ );
注意:参照表和被参照表可以是同一个表。
-
数据类型
下表给出了部分SQL标准支持的数据类型:
数据类型 | 含义 |
---|---|
CHAR(n),CHARACTER(n) | 长度为n的定长字符串 |
VARCHAR(n) | 最大长度为n的变长字符串 |
INT,INTEGER | 长整数(4字节) |
SMALLINT | 短整数(2字节) |
BIGINT | 大整数(8字节) |
FLOAT(n) | 可选精度的浮点数,精度至少为n位 |
BOOLEAN | 逻辑布尔量 |
DATE | 日期,包含年月日,格式为YYYY-MM-DD |
TIME | 时间,包含时分秒,格式为HH:MM:SS |
-
模式与表
定义基本表一般有三种方法定义它所属的模式:
-
在表名中明显给出模式名
CREATE TABLE "S-T".Student(...); /*Student所属模式是S-T*/
在创建模式语句中同时创建表
设置所属的模式,这样在创建表时表明中不必给出模式名
-
-
修改基本表
格式为:
ALTER TABLE <表名> [ADD [COLUMN] <新列名><数据类型> [完整性约束]] [ADD <表级完整性约束>] [DROP [COLUMN] <列名> [CASCADE|RESTRICT]] [DROP CONSTRAINT <完整性约束> [RESTRICT|CASCADE]] [ALTER COLUMN <列名><数据类型>];
-
删除基本表
格式为:
DROP TABLE <表名> [RESTRICT|CASCADE];
若选择RESTRICT,则该表的删除是有限制条件的。
若选择CASCADE,则该表的删除没有限制条件。在删除基本表的同时。相关的依赖对象,例如视图,都将被一起删除。
索引的建立与删除
当表的数据量比较大时,查询操作会比较耗时。建立索引可以加快查询速度。数据库索引有多种类型,常见索引包括文件上的索引、B+树索引、散列(HASH)索引、位图索引等。(了解一下)
- 顺序文件上的索引是针对按指定属性值升序或降序存储的关系,在该属性上建立一个顺序索引文件,索引文件由属性值和相应的元组指针组成。
- B+树索引是将索引属性组织成B+树形式,B+树的叶结点为属性值和相应的元组指针。此索引具有动态平衡的优点。
- 散列索引是建立若干个桶,将索引属性按照其散列函数值映射到相应桶中,桶中存放索引属性值和相应的元组指针。查找速度快。
- 位图索引是用位向量记录索引属性中可能出现的值,每个位向量对应一个可能值。
-
建立索引
格式为:
CREATE [UNIQUE] [CLUSTER] INDEX <索引名> ON <表名>(<列名> [<次序>] [,<列名> [<次序>]]...);
表名是要建立的基本表的名字。索引可以建立在该表的一列或多列上,各列名之间用逗号隔开。每个列名后可以用次序指定索引值得排列次序,可选
ASC
(升序)或DESC
(降序),默认值是升序。UNIQUE
表明此索引的每一个索引值只对应唯一的数据记录。CLUSTER
表示要建立的索引是聚簇索引。 -
修改索引
格式为:
ALTER INDEX <旧索引名> RENAME TO <新索引名>;
-
删除索引
格式为:
DROP INDEX <索引名>;
删除索引时,系统会同时从数据字典中删去有关该索引的描述。
数据字典
数据字典是关系数据库管理系统内部的一组系统表,记录了数据库所有的定义信息。关系数据库管理系统在执行SQL的数据定义语句时,实际上就是在更新数据字典表中的相应信息。
数据查询(重难点)
格式为:
SELECT [ALL|DISTINCT] <目标列表达式> [,<目标列表达式>] ...
FROM <表名或视图名> [,<表名或视图名>...]|(
含义是:根据WHERE
子句的条件表达式从FROM子句指定的基本表中找出满足条件的元组,再按SELECT
子句中的目标列表达式选出元组中的属性值形成结果表。如果有GROUP BY
子句,则将结果按列名1进行分组,该属性列值相等的元组为一个组。如果有ORDER BY
子句,则结果表还要按列名2的值得升序或降序排序。
注意:索引的ASC|DESC
是建立对象时方便查询的,而查询的ORDER BY
的ASC|DESC
是对结果表进行的一次排序。
单表查询
-
选择表中的若干列
-
查询指定列
SELECT Sno,Sname FROM Student;
-
查询全部列
SELECT * FROM Student;
-
查询经过计算的值
目标列表达式不仅可以是表中的属性列,还可以是表达式
SELECT Sname,2017-Sage FROM Student;
-
-
选择表中的若干元组
-
消除取值重复的行
SELECT DISTINCT Sno FROM SC;
查询满足条件的元组
-
查询条件 | 谓词 |
---|---|
比较 | =, >, <, >=, <=, !=, <>, !>, !< ; NOT+上述比较运算符 |
确定范围 | BETWEEN AND, NOT BETWEEN AND |
确定集合 | IN, NOT IN |
字符匹配 | LIKE, NOT LIKE |
空值 | IS NULL, IS NOT NULL |
多重条件 | AND, OR, NOT |
-
比较大小
SELECT Sname FROM Student WHERE Sdept='CS';
-
确定范围
SELECT Sname,Sdept,Sage FROM Student WHERE Sage BETWEEN 20 AND 25;
-
确定集合
SELECT Sname,Ssex FROM Student WHERE Sdept IN ('CS','MA','IS');
-
字符匹配
[NOT] LIKE '<匹配串>' [ESCAPE '<换码字符>']
匹配串可以是一个完整的字符串,也可以含有通配符%和_(模糊查询)。
- %代表任意长度的字符串
- _下划线代表任意单个字符
- []指定范围( [a-f] 或 [abcdef] )中的任何单个字符
SELECT * FROM Student WHERE Sname LIKE '刘%';
如果用户要查询的字符串本身就含有通配符,就要使用
ESCAPE '换码字符'
短语对通配符进行转义了。SELECT Cno,Ccredit FROM Student WHERE Cname LIKE 'DB\_Design' ESCAPE '\';
-
涉及空值的查询
SELECT Sno,Cno FROM SC WHERE Grade IS NULL /*不能写 = null*/
-
多重条件查询
SELECT Sname FROM Student WHERE Sdept='CS' AND Sage<20;
-
ORDER BY 子句
SELECT Sno,Grade FROM SC WHERE Cno='3' ORDER BY Grade DESC;
对于空值,排序时显示的次序由具体系统实现来决定。
-
聚集函数
SQL提供了许多聚集函数,主要有:
函数名 | 说明 |
---|---|
COUNT(*) | 统计元组个数 |
COUNT( [DISTINCT/ALL] <列名> ) | 统计一列中值的个数 |
SUM( [DISTINCT/ALL] <列名> ) | 计算一列值的总和(必须是数值型) |
AVG( [DISTINCT/ALL] <列名> ) | 计算一列值得平均值(数值型) |
MAX( [DISTINCT/ALL] <列名> ) | 求一列值中的最大值 |
MIN( [DISTINCT/ALL] <列名> ) | 求一列值中的最小值 |
当聚集函数遇到空值时,除COUNT(*)
外,都跳过空值而只处理非空值。
注意:WHERE
子句是不能用聚集函数作为条件表达式的。聚集函数只能用于SELECT
子句和GROUP BY
中的HAVING
子句。
- GROUP BY 子句
对查询结果分组的目的是为了细化聚集函数的作用对象。如果未对查询结果分组,聚集函数将作用于整个查询结果(毫无实际意义)。分组后聚集函数将作用于每一个组,即每一个组都有一个函数值。用GROUP BY子句后,SELECT中的属性列只能有标签属性(就是GROUP BY子句后跟的属性列)和聚集函数。
连接查询
若一个查询同时涉及两个以上的表,则称之为连接查询。
- 等值与非等值连接查询
连接查询的WHERE子句中用来连接两个表的条件称为连接条件或连接谓词。比较运算符有=、>、<、>=、<=、!=或<>
等。当连接运算符为=时,成为等值连接。使用其他运算符称为非等值连接。连接谓词中的列名称为连接字段。连接条件中的各连接字段类型必须是可比的,但名字不必相同。对于两表或多表中名字唯一的属性列前不用加前缀,但相同属性名的引用必须加上表名前缀。如:
select Student.Sno,Sname,Sage
from Student,SC
where Student.Sno=SC.Sno /*Sno属性列重名,引用时加上表名前缀防止产生歧义*/
- 自身连接
连接操作还可以时一个表与其自己进行连接,称为表的自身连接。当然,自身连接中要为同表取两个别名,一个是FIRST,另一个是SECOND(并没有严格的命名要求,能区别两表即可)。 - 外连接
在通常的连接操作中,只有满足条件的元组才能作为结果输出。有时我们想把某表的悬浮元组保存在结果关系中,而在另一个表中的属性上填控制NULL,这时需要用外连接。左外连接列出左边关系中所有的元组,右外连接列出右边关系中所有的元组。全外连接不仅返回左表中不符合连接条件单符合查询条件的数据行,还返回表中不符合连接条件单符合查询条件的数据行,实际上就是左外连接和右外连接的数学合集(去掉重复),即全外连接=左外连接 UNION 右外连接。
外连接格式为:
/*a,b,c,d均是属性列,A,B是表*/
/*下列代码依次对应左外连接右外连接和全连接,其中的outer可以缺省*/
select A.d,a,b,c
from A left/right/full [outer] join B on (A.d=B.d);
嵌套查询
在SQL语言中,一个SELECT-FROM-WHERE语句称为一个查询块。将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询。
注意:子查询的SELECT语句中不能使用ORDER BY子句。
- 带有IN谓词的子查询
若子查询的查询条件不依赖于父查询,称为不相关查询。如果子查询的查询条件依赖于父查询,这类子查询称为相关子查询,整个查询语句称为相关嵌套查询。 - 带有比较运算符的子查询
求解相关子查询不能像求解不相关子查询一样一次将子查询求解出来,然后求解父查询,内层查询由于与外层查询有关,因此必须反复求值。 - 带有ANY或ALL谓词的子查询
子查询返回单值时可以用比较运算符,但返回多值时要用比较运算符
+ANY或ALL
谓词修饰符。 - 带有EXISTS谓词的子查询
带有EXISTS谓词的子查询不返回任何数据,只产生true或false。
(这里缺一块最难的部分,因为笔者目前在用平板写博文没有LaTex数学公式手册,且不清楚是否支持公式,故日后再做更新)
集合查询
SELECT语句的查询结果是元组的集合,所以多个SELECT语句的结果可进行集合操作。集合的操作主要包括并操作UNION、交操作INTERSECT和差操作EXCEPT。
注意:参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同。集合查询语句放在两个查询块之间。
基于派生表的查询
子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表称为主查询的查询对象。通过FROM子句生成派生表时,AS关键字可以省略,但必须为派生表关系指定一个别名,对于基本表,别名是可选项。
SELECT语句的一般格式
数据更新
插入数据
格式为:
INSERT
INTO 表名 属性列1,属性列2,...
VALUES 常量1,常量2,...;
/*有几个属性列对应赋几个常量值*/
/*赋值时字符串常数要用单引号或双引号括起来*/
修改数据
格式为:
UPDATE 表名
SET 属性列1=值或表达式,属性列2=值或表达式,...
[WHERE 条件];
/*如果省略where子句,说明要修改表中的所有元组(set后面跟的属性列的值全部被修改)*/
删除数据
格式为:
DELETE
FROM 表名
[WHERE 条件];
/*delete删除的是表中的数据,不是关于表的定义*/
空值的处理
所谓空值就是“不知道”或“不存在”或“无意义”的值。SQL语言中一般如下情况取空值:
- 该属性应该有一个值但目前不知道它的具体值。
- 该属性不该有值。
- 由于某种原因不便于填写。
视图
视图是从一个或几个基本表(或视图)导出的表。它是一个虚表。数据库中只存放视图的定义,而不存放视图对应的数据,这些数据仍存放在原来的基本表中。
定义视图
建立视图
格式为:
CREATE VIEW 视图名 列名1,列名2,...
AS 子查询
[WITH CHECK OPTION]
/*其中子查询可以是任意的select语句*/
WITH CHECK OPTION
表示对视图进行UPDATE、INSERT和DELETE
操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)。注意:组成视图的属性列要么全部省略要么全部指定,出现下列三种情况时必须明确指定组成视图的所有列名:
- 某个目标列不是单纯的属性名,而是聚集函数或列表达式;
- 多表连接时选出了几个同名列作为视图的字段;
- 需要在视图中为某个列启用新的更合适的名字。
关系数据库管理系统执行create view
语句的结果只是把视图的定义存入数据字典,并不执行其中的select
语句。
若一个视图是从但个基本表导出的,并且只是去掉了基本表的某些行和某些列,但保留了主码,则称这类视图为行列子集视图。注意:行列子集视图是可以进行更新操作的。
定义基本表时,表中只存放基本数据,派生出的数据一般不存储。把这些派生属性列称为虚拟列。
如果用带有聚集函数和GROUP BY子句的查询来定义视图,这种视图称为分组视图。
删除视图
格式为:
DROP VIEW 视图名 [CASCADE]
/*cascade表示级联删除*/
查询视图
关系数据库管理系统执行对视图的查询时,首先进行有效性检查,检查查询中涉及的表或视图是否存在。如果存在,则从数据字典中取出视图的定义,把定义中的子查询和用户的查询结合起来,转换成等价的对基本表的查询,然后再执行修正了的查询。这一过程称为视图消解。
注意:视图一旦定义,其定义将永久保存在数据字典中,之后的所有查询都可以直接应用该视图。而派生表只是在语句执行时临时定义,语句执行后该定义即被删除。
更新视图
只允许行列子集视图进行更新。对视图的更新最终要转换成对基本表的更新。
对于视图的更新,不同的系统在实现方法上有差异,其中DB2规定:
- 若视图是由两个以上基本表导出的,则此视图不允许更新;
- 若视图的字段来自字段表达式或常数,则只允许对此视图执行
DELETE
操作; - 若视图的字段来自聚集函数,则此视图不允许更新;
- 若视图定义中含有
GROUP BY
子句,则此视图不允许更新; - 若视图定义中含有
DISTINCT
短语,则此视图不允许更新; - 若视图定义中有嵌套查询,并且内层查询的
FROM
子句中涉及的表也是导出该视图的基本表,则此视图不允许更新; - 一个不允许更新的视图上定义的视图也不允许更新。
视图的作用
- 视图能够简化用户的操作
- 视图使用户能以多种角度看待统一数据
- 视图对重构数据库提供了一定程度的逻辑独立性
- 视图能够对机密数据提供安全保护
- 适当利用视图可以更清晰地表达查询
欢迎访问我的个人博客