写在前面:本篇博客大部分内容参考数据库系统概念(本科教学版)第三章
SQL的组成
PS:其中DDL、DML、integrity有一些补充,剩下的几项都是课本内容,应该后面会讲到。现在就先放在那边吧
数据定义语言(Data-Definition Language, DDL)
- 提供定义关系模式,删除关系以及修改关系模式的命令
- 如create、drop、alter等执行以后会产生、销毁表(定义、删除关系模式)或改变表的结构(修改关系模式)
数据操纵语言(Data-Manipulation Language,DML)
- SQL DML提供从数据库中查询信息,以及在数据库中插入元组、删除元组、修改元组的能力
- 只是对表中数据的增删改查,并没有实际影响表的结构(即关系模式并没有改变,改变的只是表中的数据)
完整性约束(integrity)
- SQL DDL 会给每一个关系(每一张表)在定义或者修改的时候定义一定的完整性约束。之后所有的操作都应该满足这些约束,不满足的操作将不被允许执行
复习注释: 不过如果对违反约束的行为做了处理,有些违反约束的语句也是可以成功执行的。比如在定义外键的时候指定了级联删除,那么一旦删除语句违反了外键约束,数据库不是拒绝执行,而是级联删除相关数据
- 比如主键约束表示一个或多个字段唯一标识了一行数据,如果试图插入主键值相同的数据,就不会被允许
- 具体的下面会单独说明并举例
- SQL DDL 会给每一个关系(每一张表)在定义或者修改的时候定义一定的完整性约束。之后所有的操作都应该满足这些约束,不满足的操作将不被允许执行
视图定义(view definition)
- SQL DDL 包括定义视图的命令
事务控制(transaction control)
- SQL包括定义事务的开始和结束的命令
嵌入式SQL和动态SQL(embedded SQL)
- 嵌入式和动态SQL定义SQL语句如何嵌入到通用编程语言,如C、C++、Java
授权
- SQL DDL包括定义对关系和视图的访问权限的命令
基本类型
这些基本数据类型不依赖于某一个具体的数据库,是SQL数据库通用的类型
char(n)——全称character
- 用户指定长度的字符串,所有取值的长度都固定为长度为n的char
- 比如身份证或者电话号码等长度固定的数据可以使用这个
- 一般实际用的较少
varchar(n)——全称character varying
- 可变长的字符串,n为串的最大允许长度
- 实际存的时候数据多长,就存多长,较省空间
- 实际应用中大多用varchar,而不是char
int——integer
- 整数类型,没啥好讲的,Oj8k
smallint
- 小整数类型
numeric(p, d)
- 定点数,这个数有p位数字,其中小数点右边有d位
- 例如,numberic(3, 1)可表示-99.9 ~ 99.9
下面在MySQL数据库上面的测试,举个栗子:(测试结果表明,如果定义numberic(3, 1), 则小数点前面有三位数时是无法插入的,如果小数点后面有多位小数,则通过四舍五入的方法只保留一位小数)
先简单定义一张Student表(没有定义主键,允许插入相同的数据)
1
2
3
4
5
6-- 下面定义了一张学生表,其中grade的取值范围为-99.9 ~ 99.9(不合理的取值,只是为了测试)
CREATE TABLE Student (
study_id VARCHAR(20) NOT NULL,
age INTEGER DEFAULT 0,
grade NUMERIC(3, 1)
);执行正常的插入操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-- 下面两条插入语句都能正常执行,并且结果正确
INSERT INTO Student(study_id, age, grade) VALUES (
'201590001', 18, 92.5
)
INSERT INTO Student(study_id, age, grade) VALUES (
'201590002', 18, -92.5
)
-- 执行下面一条插入操作,最后保存的记录是 -92.6,
INSERT INTO Student(study_id, age, grade) VALUES (
'201590003', 18, -92.56
)
-- 执行下面一条插入操作,最后保存的记录是 -92.5,
INSERT INTO Student(study_id, age, grade) VALUES (
'201590004', 18, -92.54
)
-- 下面的这条插入操作将会报错
-- [22001][1264] Data truncation: Out of range value for column 'grade' at row 1
INSERT INTO Student(study_id, age, grade) VALUES (
'201590005', 18, 192.5
)执行上面操作后的结果
study_id | age | grade |
---|---|---|
201590001 | 18 | 92.5 |
201590002 | 18 | -92.5 |
201590003 | 18 | -92.6 |
201590004 | 18 | -92.5 |
SQL中的完整性约束
下文中列举的只是部分简单约束,具体的会在后面的内容中讨论
先来简单聊一聊我对完整性约束的理解吧,其实数据库中的完整性约束讲起来就是数据库在定义一张表的时候,对其作出了一系列的约束(这些个约束可能影响一个或多个字段,甚至影响整个表结构)。如果后续的操作中(不管是DDL还是很DML),如果违背了之前定义的约束,(如果没有对违反约束行为做特殊的处理)这个操作就不会成功
primary key(A1, A2, …, An)——主键约束
- 该约束主要指定了以属性A1~An构成关系的主键,该主键值必须非空且唯一
- 即只要一个表的主键确定,那这个表中就不允许存在一行数据其主键的值为null, 也不允许存在两行数据其主键的值一样。一旦后续操作违反了这个原则(约束),则该操作就不会被执行
举个栗子:
新定义一张department表
1
2
3
4
5
6
7-- 下面的操作创建了一张department表,并指定dept_name为主键
CREATE TABLE department (
dept_name VARCHAR(20),
building VARCHAR(15),
budget NUMERIC(12, 2),
PRIMARY KEY (dept_name)
);下面顺序执行一系列插入操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14-- 下面的操作将成功插入一条记录
INSERT INTO department (dept_name, building, budget)
VALUES ('Software', 'A', 100000);
-- 下面再执行一次与上面一模一样的操作,会发现报错,因为之前已经有一条
-- 记录的主键值为'Software',顾无法再插入主键值相同的数据
-- [23000][1062] Duplicate entry 'Software' for key 'PRIMARY'
INSERT INTO department (dept_name, building, budget)
VALUES ('Software', 'A', 100000);
-- 下面的语句试图插入一条dept_name为空的数据,显然也是报错的
-- 因为作为主键的字段是不允许为空的
-- [23000][1048] Column 'dept_name' cannot be null
INSERT INTO department (dept_name, building, budget) VALUES (NULL , 'A', 100000);执行上面操作后的结果
dept_name | building | budget |
---|---|---|
Software | A | 100000 |
foregin key(A1, A2, …, An) references —— 外键约束
- 简单来讲如果一个关系(表)A中包含一个外键C,则作为外键的一个或多个字段必然是另一张表B的主键。则由于外键约束这一层关系,对A表和B表都会收一定程度的限制(现在解释的还是比较抽象,看下面的例子会比较直观一点)
- 如果想向A表中插入一条数据,且数据中C的值在B表中找不到对应表项,则这个操作不会成功(就像你如果向运动员表中插入一条数据,国家属性对应的标识在国家表中不存在,则这次插入操作就会失败)
- 如果试图删除一个表B的记录,而这条记录的主键只正好是A表中某条数据的外键,则这次删除操作不会成功
举个栗子:
先创建两张表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17-- 创建一张表department,并制定dept_name为主键
CREATE TABLE department (
dept_name VARCHAR(20),
building VARCHAR(15),
budget NUMERIC(12, 2),
PRIMARY KEY (dept_name)
);
-- 再创建一张couese表,并指定dept_name为本表关于department表的外键
CREATE TABLE course (
course_id VARCHAR(7) NOT NULL,
title VARCHAR(50),
dept_name VARCHAR(20),
credits NUMERIC(2, 0),
PRIMARY KEY (course_id),
FOREIGN KEY (dept_name) REFERENCES department (dept_name)
);我们先试图插入一条course记录
1
2
3
4-- 下面试图往course表中插入一条记录,但是department表中并没有
-- dept_name = 'DUT'的记录,故该操作会失败
INSERT INTO course (course_id, title, dept_name, credits)
VALUES ('08', 'English', 'DUT', 3)我们先往department表中插入记录,再往course表中插入记录,下面的操作就能成功插入
1
2
3
4
5
INSERT INTO department (dept_name, building, budget) VALUES ('DUT' , 'A', 100000);
INSERT INTO course (course_id, title, dept_name, credits)
VALUES ('08', 'English', 'DUT', 3)- 执行上面操作后的结果
- 简单来讲如果一个关系(表)A中包含一个外键C,则作为外键的一个或多个字段必然是另一张表B的主键。则由于外键约束这一层关系,对A表和B表都会收一定程度的限制(现在解释的还是比较抽象,看下面的例子会比较直观一点)
dept_name | building | budget |
---|---|---|
DUT | A | 100000 |
course_id | title | dept_name | credits |
---|---|---|---|
08 | Endlish | DUT | 3 |
* 此时我们如果试图删除department表中dept_name = DUT的那条数据
1
2
3
-- 执行下面的操作就会报错,因为course表中还有一项数据的dept_name的值为DUT,如果删除掉department中的这条数据,就会破坏其完整性,顾执行失败
-- 23000][1451] Cannot delete or update a parent row: a foreign key constraint fails (`db_study`.`course`, CONSTRAINT `course_ibfk_1` FOREIGN KEY (`dept_name`) REFERENCES `department` (`dept_name`))
DELETE FROM department WHERE dept_name = 'DUT';
* 同样的如果,我们试图删除department表,则只要course表中还有数据,这个操作就会失败
打赏
如果你觉得本篇博文写的还过得去,而且乐意随手打赏,将是对博主最大的鼓励~