SQL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1. 什么是 SQL?
Structured Query Language:结构化查询语言
其实就是定义了操作所有关系型数据库的规则。每一种数据库操作的方式存在不一样的地方,称为“方言”。

2.SQL 通用语法
1. SQL 语句可以单行或多行书写,以分号结尾。
2. 可使用空格和缩进来增强语句的可读性。
3. MySQL 数据库的 SQL 语句不区分大小写,关键字建议使用大写。
4. 3 种注释
* 单行注释: -- 注释内容 或 # 注释内容(mysql 特有)
* 多行注释: /* 注释 */

3. SQL 分类
1) DDL(Data Definition Language) 数据定义语言
用来定义数据库对象:数据库、表、列等。关键字:create, drop,alter 等
2) DML(Data Manipulation Language) 数据操作语言
用来对数据库中表的数据进行增、删、改。关键字:insert, delete, update 等
3) DQL(Data Query Language) 数据查询语言
用来查询数据库中表的记录(数据)。关键字:select, where 等
4) DCL(Data Control Language) 数据控制语言(了解)
用来定义数据库的访问权限和安全级别,及创建用户。关键字:GRANT, REVOKE 等

DDL:操作数据库

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
26
27
28
29
1. 操作数据库:CRUD
1. C(Create): 创建
* 创建数据库:
* create database 数据库名称;
* 创建数据库,判断不存在,再创建:
* create database if not exists 数据库名称;
* 创建数据库,并指定字符集
* create database 数据库名称 character set 字符集名;

* 练习: 创建 db4 数据库,判断是否存在,并制定字符集为 gbk
* create database if not exists db4 character set gbk;
2. R(Retrieve):检索(查询)
* 查询所有数据库的名称:
* show databases;
* 查询某个数据库的字符集: 查询某个数据库的创建语句
* show create database 数据库名称;
3. U(Update): 修改
* 修改数据库的字符集
* alter database 数据库名称 character set 字符集名称;
4. D(Delete): 删除
* 删除数据库
* drop database 数据库名称;
* 判断数据库存在,存在再删除
* drop database if exists 数据库名称;
5. 使用数据库
* 查询当前正在使用的数据库名称
* select database();
* 使用数据库
* use 数据库名称;

操作数据库实例演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 查询所有数据库的名称 
SHOW DATABASES;

-- 查看某个数据库的字符集(查看某个数据库的创建语句)
SHOW CREATE DATABASE mysql;

-- 判断后(若不存在) 创建 db 数据库,并指定
CREATE DATABASE IF NOT EXISTS db CHARACTER SET utf8;

-- 修改指定数据库的字符集
ALTER DATABASE db CHARACTER SET gbk;

-- 判断数据库是否存在,存在则删除
DROP DATABASE IF EXISTS db;

-- 查询正在使用的数据库名称
SELECT DATABASE();

-- 使用某个数据库
USE db;

DDL:操作数据表

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2. 操作表
1. C(Create): 创建
* 创建表语法:
create table 表名(
列名 1 数据类型 1,
列名 2 数据类型 2,
....
列名 n 数据类型 n
);
* 数据库类型:
1. int:整数类型
2. double: 小数类型
3. date: 日期,只包含年月日 yyyy-MM-dd
4. datetime: 日期,包含年月日时分秒 yyyy-MM-dd HH:mm:ss
5. timestamp: 时间戳类型 包含年月日时分秒 yyyy-MM-dd HH:mm:ss
* 如果将来不给这个字段赋值,或赋值为 null,则默认使用当前的系统时间,来自动赋值
6. varchar:字符串
* 复制表语法:
* create table 表名 like 被复制的表名;
2. R(Retrieve):检索(查询)
* 查询某个数据库中所有的表名称
* show tables;
* 查询表结构
* desc 表名;
3. U(Update): 修改
1. 修改表名
alter table 表名 rename to 新的表名;
2. 修改表的字符集
alter table 表名 character set 字符集名称;
3. 添加一列
alter table 表名 add 列名 数据类型;
4. 修改列名称、类型
alter table 表名 change 列名 新列别 新数据类型;
alter table 表名 modify 列名 新数据类型;
5. 删除列
alter table 表名 drop 列名;
6. 修改字段排列顺序 / 在增加的时候指定字段位置:FIRST 或者 AFTER 字段名
ALTER TABLE 表名 ADD 字段名 数据类型 FIRST;
ALTER TABLE 表名 ADD 字段名 数据类型 AFTER 字段名;
ALTER TABLE 表名 CHANGE 字段名 旧字段名 新字段名 新数据类型 FIRST;
ALTER TABLE 表名 MODIFY 字段名 数据类型 AFTER 字段名;
4. D(Delete): 删除
* drop table 表名;
* drop table if exists 表名;

操作表实例演示

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
26
27
28
29
30
31
32
33
-- 查询某个数据库中所有表名称
SHOW TABLES;

-- 创建表
CREATE TABLE student(`name` VARCHAR(20), age INT, score DOUBLE(5,2), DATA TIMESTAMP);

-- 复制表
CREATE TABLE stu LIKE student;
CREATE TABLE IF NOT EXISTS stu LIKE student;

-- DESC: description, 查询表结构
DESC student;

-- 修改表名
ALTER TABLE stu RENAME TO teacher;

-- 修改表的字符集
ALTER TABLE student CHARACTER SET gbk;

-- 给表添加一列
ALTER TABLE student ADD id INT;

-- 修改某一列的名称并重新指定该列的数据类型
ALTER TABLE student CHANGE id user_id INT;

-- 修正某一列的数据类型但不修改列名称
ALTER TABLE student MODIFY user_id BIGINT;

-- 删除表中的某一列
ALTER TABLE student DROP user_id;

-- 判断表是否存在, 存在则删除该表
DROP TABLE IF EXISTS teacher;

DML:增删改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1. 添加数据:
* 语法:
* insert into 表名 (列名 1, 列名 2,... 列名 n) values(值 1, 值 2,... 值 n);
* 注意:
1. 列名和值要一一对应。
2. 如果表名后,不定义列名,则默认给所有列添加值
insert into 表名 values(值 1, 值 2,... 值 n);
3. 除了数字类型,其他类型的值需要使用引号(单双都可以) 引起来
2. 删除数据:
* 语法:
* delete from 表名 [where 条件];
* 注意:
1. 如果不加条件,则删除表中所有记录。
2. 如果要删除所有记录
1. delete from 表名; -- 不推荐使用。有多少条记录就会执行多少次删除操作,效率低
2. TRUNCATE TABLE 表名; -- 推荐使用,效率更高 先删除表,然后再创建一张一样的表
3. 修改数据:
* 语法:
* update 表名 set 列名 1 = 值 1, 列名 2 = 值 2,... [where 条件];
* 注意:如果不加任何条件,则会将表中所有记录全部修改。

增删改演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 往表中指定的列插入数据 
INSERT INTO student(user_id, NAME, age, score) VALUES(7, " 小傻瓜 ", 12, 72.56);

-- 按条件删除表中的数据, 如果不加条件则逐条删除数据直到为空表
DELETE FROM student WHERE user_id = 1;

-- 逐条删除数据直到为空表, 效率慢避免误操作, 慎用
DELETE FROM student;

-- 删除表, 并创建一个与之前表结构完全相同的空表, 效率高(等价于 DELETE FROM student;) 推荐使用
TRUNCATE TABLE student;

-- 按条件修改表中的数据
UPDATE student SET age = 17, score = 95.28 WHERE user_id = 1

DQL:查询

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
* select * from 表名;

1. 查询表中的记录语法:
select
字段列表
from
表名列表
where
条件列表
group by
分组字段
distinct
去重
having
分组之后的条件
order by
排序
limit
分页限定

2. 基础查询
1. 多个字段的查询:
select 字段名 1,字段名 2... from 表名;
* 注意:如果查询所有字段,则可以使用 * 来替代字段列表。
2. 查询多个字段,但去除多余的重复记录:
* select distinct 字段名 1,字段名 2... from 表名;
3. 计算列:
* 一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算)
* ifnull(表达式 1, 表达式 2):null 参与的运算,计算结果都为 null
* 表达式 1:哪个字段需要判断是否为 null,如果该字段为 null,则替换为表达式 2 的值
4. 起别名:
* as:as 也可以省略

3. 条件查询
1. where 子句后跟条件
2. 运算符
* > 、< 、<= 、>= 、= 、<>(不等于)
* BETWEEN...AND
* IN(集合)
* LIKE:模糊查询
* 占位符:
* _: 单个任意字符
* %:多个任意字符
* IS NULL
* and 或 &&
* or 或 ||
* not 或 !

查询演示

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
26
27
28
29
30
31
32
33
34
35
36
37
38
-- 查看表中的所有列的记录: SELECT * FROM 表名;
SELECT * FROM student;

-- 多个字段 (列) 查询语法: SELECT 字段名 1, 字段名 2, ... FROM 表名;
SELECT age, score FROM student;

/*
* 多个字段去重语法: SELECT DISTINCT 字段名 1, 字段名 2, ... FROM 表名;
*/
-- 去重被选择的多个字段 (列) 中存在完全重复的字段, 只保留一个
SELECT DISTINCT age, score FROM student;

-- 选择多个字段(列), 并对特定的列进行四则运算, 并作为(AS) 新列
SELECT DISTINCT age, score, age * 100 + IFNULL(score, 0) AS combine FROM student;

/*
* 按条件查询语法:WHERE 限制条件
* 注意: 判断是否为空用 xxx IS NULL / xxx IS NOT NULL
*/
SELECT * FROM student WHERE age > 10 AND age < 16;
SELECT * FROM student WHERE age BETWEEN 11 AND 15;
SELECT * FROM student WHERE age IN(14,16,17);
SELECT * FROM student WHERE score IS NULL;
SELECT * FROM student WHERE score IS NOT NULL;
SELECT * FROM student WHERE age <> 16; -- <> 表示不等于
SELECT * FROM student WHERE score < 82 OR score > 88;

-- 模糊查询:查询名字第一个字是 小 的数据(一个 % 表示多个任意字符)
SELECT * FROM student WHERE NAME LIKE " 小 %";

-- 模糊查询:查询名字第一个字是 小 的数据(一个_表示任意一个字符)
SELECT * FROM student WHERE NAME LIKE " 小__";

-- 模糊查询:查询名字中包含 小 的数据
SELECT * FROM student WHERE NAME LIKE "% 小 %";

-- 模糊查询:查询名字中不包含 小 的数据
SELECT * FROM student WHERE NAME NOT LIKE "% 小 %";

DQL:排序查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1. 排序查询
* 语法: order by 子句
* order by 排序字段 1 排序方式 1, 排序字段 2 排序方式 2...;
* 排序方式:
* ASC:升序,默认的
* DESC:降序
* 注意:
* 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件
2. 聚合函数:将一列数据作为一个整体,进行纵向的计算。

1. count:计算个数
1. 一般选择非空的列:主键
2. count(*)
2. max:计算最大值
3. min:计算最小值
4. sum:计算和
5. avg:计算平均值

* 注意:聚合函数的计算,排除 null 值。
解决方案:
1. 选择不包含非空的列进行计算
2. IFNULL 函数

排序查询演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* 
* 排序查询语法: ORDER BY 排序字段 1 排序方法 1, 排序字段 2 排序方法 2, ...
* 升序 ASC, 降序 DESC 排序
*/
SELECT * FROM student ORDER BY score ASC;

-- 按第一规则 age 升序, age 相同时按第二规则 score 降序
SELECT * FROM student ORDER BY age ASC, score DESC;

/*
* 聚合函数: 将一列数据作为一个整体, 进行纵向计算.
* COUNT(), MAX(), MIN(), SUM(), AVG()
*/
-- 统计数据条数
SELECT COUNT(user_id) FROM student;

-- 统计数据条数(COUNT 默认不统计 null, 使用 IFNULL 增加 null 的计数)
SELECT COUNT(IFNULL(score, 0)) FROM student;

-- 聚合函数的使用
SELECT MAX(score), MIN(age), SUM(score), AVG(age) FROM student;

DQL:分组查询

1
2
3
4
5
6
7
8
3. 分组查询:
1. 语法: group by 分组字段;
2. 注意:
1. 分组之后查询的字段:分组字段、聚合函数
2. where 和 having 的区别?
1. where 在分组 group by 之前进行限定,如果不满足条件,则不参与分组。
2. having 在分组 group by 之后进行限定,如果不满足结果,则不会被查询出来。
3. where 后不可以跟聚合函数,having 可以进行聚合函数的判断。

分组查询演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- 按照性别分组,分别查询男、女同学的平均分
SELECT sex, AVG(math) FROM student GROUP BY sex;

-- 按照性别分组,分别查询男女同学的平均分和人数
SELECT sex, AVG(math), COUNT(id) FROM student GROUP BY sex;

-- 按照性别分组,分别查询男女同学的平均分、人数,要求:分数低于 70 分的人不参与分组
SELECT sex, AVG(math), COUNT(id) FROM student WHERE math >= 70 GROUP BY sex;

-- 按照性别分组,分别查询男女同学的平均分 要求:分数低于 70 分的人不参与分组,分组之后人数要大于 2 个人才进行显示
SELECT
sex,
AVG (math),
COUNT (id) AS cnt
FROM
student
WHERE math >= 70
GROUP BY sex
HAVING COUNT (id) > 0;

DQL:分页查询

1
2
3
4
5
6
7
8
4. 分页查询
1. 语法:limit 开始的索引, 每页查询的条数;
2. 公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数
-- 每页显示 3 条记录
SELECT * FROM student LIMIT 0,3; -- 第 1 页
SELECT * FROM student LIMIT 3,3; -- 第 2 页
SELECT * FROM student LIMIT 6,3; -- 第 3 页
3. limit 是一个 MySQL" 方言 "

约束

1
2
3
4
5
6
* 概念: 对表中的数据进行限定,保证数据的正确性、有效性和完整性。	
* 分类:
1. 主键约束: primary key
2. 非空约束: not null
3. 唯一约束: unique
4. 外键约束: foreign key

非空约束演示

1
2
3
4
5
6
7
8
9
10
11
/*
* 约束: 非空约束(NOT NULL)、唯一约束(UNIQUE)、主键约束(PRIMARY KEY)、外键约束(FOREIGN KEY)
*/
-- 非空约束: 1. 在创建表时添加非空约束
CREATE TABLE stu (age INT, `name` VARCHAR (20) NOT NULL);

-- 非空约束: 2. 删除非空约束, 使用 MODIFY
ALTER TABLE stu MODIFY `name` VARCHAR (20);

-- 非空约束: 3. 创建表时未添加非空约束, 创建表之后添加非空约束
ALTER TABLE stu MODIFY `name` VARCHAR (20) NOT NULL;

唯一约束演示

1
2
3
4
5
6
7
8
9
10
/* 注意 mysql 中,唯一约束限定的列的值可以有多个 null */

-- 唯一约束: 在创建表时添加唯一约束
CREATE TABLE stu (id BIGINT UNIQUE, age INT, `name` VARCHAR (20) NOT NULL);

-- 唯一约束: 2. 删除唯一约束, 使用 drop index
ALTER TABLE stu DROP INDEX id;

-- 唯一约束: 3. 创建表时未添加唯一约束, 创建表之后添加唯一约束
ALTER TABLE stu MODIFY id BIGINT UNIQUE;

主键约束演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
* 主键约束:primary key
* 注意:
* 1. 含义:非空且唯一
* 2. 一张表只能有一个字段为主键
* 3. 主键就是表中记录的唯一标识
*/

-- 主键约束: 1. 在创建表时添加主键约束
CREATE TABLE stu (id BIGINT PRIMARY KEY, age INT, `name` VARCHAR (20));

-- 主键约束: 2. 删除主键约束使用 DROP PRIMARY KEY
ALTER TABLE stu DROP PRIMARY KEY;

-- 主键约束: 3. 创建表时未添加主键约束, 创建表之后添加主键约束(此时主键字段数据不能有重复)
ALTER TABLE stu MODIFY id BIGINT PRIMARY KEY;

-- 自动增长(AUTO_INCREMENT):常与主键约束一起使用,
-- 使用自动增长要求数据类型为数值型, 可以实现值的自动增长.
ALTER TABLE stu MODIFY id BIGINT PRIMARY KEY AUTO_INCREMENT;

外键约束演示

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
/*
* 外键约束: foreign key, 用于让不同的表之间产生关系, 从而保证数据的正确性.
* 外键约束语法: CONSTRAINT 外键名称 FOREIGN KEY (外键列) REFERENCES 主表名称(主表列名称)
* 注意: 创建外键约束的主列表名称要求不能出现重复数据(可以使用唯一约束)!
*/

-- 外键约束: 在创建表时添加外键约束约束
CREATE TABLE com (-- 主表 com
sex_id INT UNIQUE,
sex VARCHAR (20) UNIQUE
);

CREATE TABLE stu (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
age INT,
`name` VARCHAR (20),
sex INT, -- 外键列
CONSTRAINT sex_ky FOREIGN KEY (sex) REFERENCES com (sex_id) -- 外键约束
);

-- 外键约束: 2. 删除外键约束, 使用 DROP FOREIGN KEY 外键名称
ALTER TABLE stu DROP FOREIGN KEY sex_ky;

-- 外键约束: 3. 创建表时未添加外键约束, 创建表之后添加外键约束, ADD 外键约束
ALTER TABLE stu ADD constraint sex_ky foreign key (sex) references com (sex_id);

级联操作演示

1
2
3
4
5
6
7
8
9
10
11
/*
* 外键级联语法: 级联更新(ON UPDATE CASCADE), 级联删除(ON DELETE CASCADE)
* 注意: 外键级联操作要配合外键约束使用
*/

-- 外键级联: 给外键约束添加外键级联, 添加时要先删除外键约束再添加外键级联
ALTER TABLE stu
DROP FOREIGN KEY sex_ky; -- 删除外键约束

ALTER TABLE stu
ADD CONSTRAINT sex_ky FOREIGN KEY (sex) REFERENCES com (sex_id) ON UPDATE CASCADE ON DELETE CASCADE; -- 添加外键级联

数据库设计之多表关系

1. 多表之间的关系
	1. 分类:
		1. 一对一(了解):
			* 如:人和身份证
			* 分析:一个人只有一个身份证,一个身份证只能对应一个人
		2. 一对多(多对一):
			* 如:部门和员工
			* 分析:一个部门有多个员工,一个员工只能对应一个部门
		3. 多对多:
			* 如:学生和课程
			* 分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择
	2. 实现关系:
		1. 一对多(多对一):
			* 如:部门和员工
			* 实现方式:在「多」的一方建立外键,指向「一」的一方的主键
		2. 多对多:
			* 如:学生和课程
			* 实现方式:多对多关系实现需要借助第三张中间表,中间表至少包含两个字段,
					    这两个字段作为第三张表的外键,分别指向两张表的主键
		3. 一对一(了解):
			* 如:人和身份证
			* 实现方式:一对一关系实现,可以在任意一方添加唯一外键指向另一方的主键

多表关系实例演示

1
2
3
4
5
6
/*
* 四张表:用户表 A、旅游线路表 B、旅游线路分类表 C、(旅游线路收藏表 D)
* 分析关系:旅游线路分类表 C 和旅游线路表 B 关系为「一对多」,
* 用户表 A 和旅游线路表 B 关系为「多对多」, 用户可以收藏多张线路表, 一张线路表可以被多用户收藏,
* 旅游线路收藏表 D 为「中间表」.
*/

多表关系实现:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*
* -- 创建旅游线路分类表 tab_category
* cid 旅游线路分类主键,自动增长
* cname 旅游线路分类名称非空,唯一,字符串 100
*/
CREATE TABLE tab_category (
cid INT PRIMARY KEY AUTO_INCREMENT,
cname VARCHAR(100) NOT NULL UNIQUE
);

/*
* -- 创建旅游线路表 tab_route
* rid 旅游线路主键,自动增长
* rname 旅游线路名称非空,唯一,字符串 100
* price 价格
* rdate 上架时间,日期类型
* cid 外键,所属分类
*/
CREATE TABLE tab_route(
rid INT PRIMARY KEY AUTO_INCREMENT,
rname VARCHAR(100) NOT NULL UNIQUE,
price DOUBLE,
rdate DATE,
cid INT, -- 一对多实现方式:在「多」的一方建立外键,指向「一」的一方的主键
FOREIGN KEY (cid) REFERENCES tab_category(cid)
);

/*
* -- 创建用户表 tab_user
* uid 用户主键,自动增长
* username 用户名长度 100,唯一,非空
* password 密码长度 30,非空
* name 真实姓名长度 100
* birthday 生日
* sex 性别,定长字符串 1,默认为男性
* telephone 手机号,字符串 11
* email 邮箱,字符串长度 100
*/
CREATE TABLE tab_user (
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(100) UNIQUE NOT NULL,
PASSWORD VARCHAR(30) NOT NULL,
NAME VARCHAR(100),
birthday DATE,
sex CHAR(1) DEFAULT ' 男 ',
telephone VARCHAR(11),
email VARCHAR(100)
);

/*
* -- 创建收藏表 tab_favorite
* rid 旅游线路 id,外键
* date 收藏时间
* uid 用户 id,外键
* rid 和 uid 不能重复,设置复合主键,同一个用户不能收藏同一个线路两次
*/
CREATE TABLE tab_favorite (
rid INT, -- 线路 id
uid INT, -- 用户 id
`data` DATETIME,
-- 创建复合主键(联合主键)
PRIMARY KEY(rid,uid), -- 多对多关系实现需要借助第三张中间表,中间表至少包含两个字段,
-- 这两个字段作为第三张表的外键,分别指向两张表的主键
FOREIGN KEY (rid) REFERENCES tab_route(rid),
FOREIGN KEY(uid) REFERENCES tab_user(uid)
);

数据库设计的范式

2. 数据库设计的范式

 	* 概念:设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,
 		   这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
 	
	目前关系数据库有六种范式:
		   第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、
		   巴斯 - 科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)

	* 分类:
		一. 第一范式(1NF):每一列都是不可分割的原子数据项
		二. 第二范式(2NF):在 1NF 的基础上,非码属性必须完全依赖于码,
						(在 1NF 基础上, 消除非主属性对主码的部分函数依赖)
		三. 第三范式(3NF):在 2NF 基础上, 任何非主属性不依赖于其它非主属性
						(在 2NF 基础上, 消除传递依赖)
	
	* 几个概念:
		1. 函数依赖:A-->B, 如果通过 A 属性 (属性组) 的值,可以确定唯一 B 属性的值, 则称 B 依赖于 A
			# 表结构: < 学号 | 姓名 | 系名 | 系主任 | 课程 | 分数 >
			例如:学号 --> 姓名,  (学号,课程名称)--> 分数
		
		2. 完全函数依赖:A-->B, 如果 A 是一个属性组,则 B 属性值的确定需要依赖于 A 属性组中「所有」属性值
			例如:(学号,课程名称)--> 分数
		
		3. 部分函数依赖:A-->B, 如果 A 是一个属性组,则 B 属性值的确定只需要依赖于 A 属性组中「部分」属性值
			例如:(学号,课程名称)--> 姓名, 不需要依赖于 A 属性组中的课程名称就可以确定姓名
		
		4. 传递函数依赖:A-->B, B-->C, 如果通过 A 属性 (属性组) 的值,可以确定唯一 B 属性的值, 
					  再通过 B 属性 (属性组) 的值可以确定唯一 C 属性的值, 则称 C 传递函数依赖于 A
			例如:学号 --> 系名,系名 --> 系主任
		
		5. 码:在一张表中, 一个属性 (属性组) 被其他所有属性所「完全依赖」, 则称这个属性 (属性组) 为该表的码
			* 主属性:码属性组中的所有属性
			* 非主属性:除码属性组以外的属性
			例如:该表中码为 (学号,课程名称), 学号、课程名称为主属性
			     姓名 | 系名 | 系主任 | 分数 被 (学号,课程名称)码 所完全依赖

数据库的备份和还原

1. 命令行:
	* 语法:
		* 命令行备份: mysqldump -u 用户名 -p 密码 数据库名称 > 保存的路径
		* 命令行还原:
			1. 登录数据库  2. 创建数据库  3. 使用数据库  4. 执行文件: source 文件路径

数据库备份和还原实例演示

1
2
3
4
5
6
7
8
9
10
/* 命令行备份 */
mysqldump -uroot -proot db > d:/save_path/save_name.sql

DROP DATABASE db; -- 删除数据库

/* 命令行还原 */
SHOW DATABASES; -- 登陆数据库
CREATE DATABASE db; -- 创建数据库
USE db; -- 使用数据库
source d:/save_path/save_name.sql -- 执行 SQL 文件还原数据库

多表查询

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
* 准备 SQL 数据
*/

-- 创建部门表
CREATE TABLE dept (
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR (20)
);

INSERT INTO dept (`name`)
VALUES
(' 开发部 '),
(' 市场部 '),
(' 财务部 ');

-- 创建员工表
CREATE TABLE emp (
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR (10),
gender CHAR (1),
salary DOUBLE,
join_date DATE,
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES dept (id) -- 外键, 关联部门表(部门表的主键)
);

INSERT INTO emp (
`name`,
gender,
salary,
join_date,
dept_id
)
VALUES
(' 孙悟空 ', ' 男 ', 7200, '2013-02-24', 1),
(' 猪八戒 ', ' 男 ', 3600, '2010-12-02', 2),
(' 唐僧 ', ' 男 ', 9000, '2008-08-08', 2),
(' 白骨精 ', ' 女 ', 5000, '2015-10-07', 3),
(' 蜘蛛精 ', ' 女 ', 4500, '2011-03-14', 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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
* 笛卡尔积:
* 有两个集合 A, B, 取这两个集合的所有可能的组合情况构成的表即为笛卡尔积.
* 要完成多表查询,需要消除无用的数据.

* 多表查询的分类:
1. 内连接查询:
1. 隐式内连接:使用 where 条件消除无用数据
* 例如:
-- 查询所有员工信息和对应的部门信息
SELECT * FROM emp, dept WHERE emp.`dept_id` = dept.`id`;

-- 查询员工表的名称、性别, 部门表的名称
SELECT
emp.name,
emp.gender,
dept.name
FROM
emp,
dept
WHERE emp.`dept_id` = dept.`id`;

2. 显式内连接:
* 语法: SELECT 字段列表 FROM 表名 1 [INNER] JOIN 表名 2 ON 连接条件;
* 例如:
SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;

3. 内连接查询:
1. 从哪些表中查询数据 2. 条件是什么 3. 查询哪些字段

2. 外连接查询:
1. 左外连接:查询的是左表所有数据以及其左表与右表的交集部分.
* 语法: SELECT 字段列表 FROM 表 1 LEFT [OUTER] JOIN 表 2 ON 连接条件;
* 例子:
-- 查询所有员工信息, 如果员工有部门, 则查询部门名称, 没有部门, 则不显示部门名称
-- 注: 如果简单的使用隐式内连接的话, 没有部门(NULL) 的员工将不会被查询到
SELECT
t1.*,
t2.`name`
FROM
emp t1
LEFT JOIN dept t2
ON t1.`dept_id` = t2.`id`;
2. 右外连接:查询的是右表所有数据以及其右表与左表的交集部分.
* 语法: SELECT 字段列表 FROM 表 1 RIGHT [OUTER] JOIN 表 2 ON 连接条件;
* 例子:
SELECT
t1.*,
t2.`name`
FROM
dept t1
RIGHT JOIN emp t2
ON t1.`id` = t2.`dept_id`;
3. 全外连接:显示左右两个表全部记录
* 语法:左外连接语句 union 右外连接语句;
* union 与 union all 的区别: union 会去掉相同的纪录, union all 不会去掉相同记录

子查询

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
3. 子查询:
* 概念:查询中嵌套查询,称嵌套查询为子查询。
-- 查询工资最高的员工信息, 一条 sql 就完成这个操作, 子查询
SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp);

* 子查询的不同情况:
1. 子查询的结果是「单行单列」的:
* 子查询可以作为条件,使用运算符 > >= < <= = 来判断
-- 查询员工工资小于平均工资的人
SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp);

2. 子查询的结果是「多行单列」的:
* 子查询可以作为条件,使用运算符 IN 来判断
-- 查询 ' 财务部 ' 和 ' 市场部 ' 所有的员工信息, 子查询
SELECT
*
FROM
emp
WHERE dept_id IN
(SELECT
id
FROM
dept
WHERE NAME IN (' 财务部 ', ' 市场部 '));

3. 子查询的结果是多行多列的:
* 子查询可以作为一张「虚拟表」参与查询
-- 查询员工入职日期是 2011-11-11 日之后的员工信息和部门信息, 子查询
SELECT
*
FROM
dept t1,
(SELECT
*
FROM
emp
WHERE emp.`join_date` > '2011-11-11') t2 -- 虚拟表
WHERE t1.id = t2.dept_id;

-- 普通内连接
SELECT
*
FROM
dept t1,
emp t2
WHERE t1.`id` = t2.`dept_id`
AND t2.`join_date` > '2011-11-11'

多表查询练习

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
-- 部门表
CREATE TABLE dept (
id INT PRIMARY KEY PRIMARY KEY, -- 部门 id
dname VARCHAR(50), -- 部门名称
loc VARCHAR(50) -- 部门所在地
);

-- 职务表,职务名称,职务描述
CREATE TABLE job (
id INT PRIMARY KEY,
jname VARCHAR(20),
description VARCHAR(50)
);

-- 员工表
CREATE TABLE emp (
id INT PRIMARY KEY, -- 员工 id
ename VARCHAR(50), -- 员工姓名
job_id INT, -- 职务 id
mgr INT , -- 上级领导
joindate DATE, -- 入职日期
salary DECIMAL(7,2), -- 工资
bonus DECIMAL(7,2), -- 奖金
dept_id INT, -- 所在部门编号
CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
);

-- 工资等级表
CREATE TABLE salarygrade (
grade INT PRIMARY KEY, -- 级别
losalary INT, -- 最低工资
hisalary INT -- 最高工资
);

/*
* 部门表 dept 和员工表 emp 是一对多的关系, 职务表 job 和员工表 emp 是一对多的关系
*/

-- 需求:

-- 1. 查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
SELECT
emp.`id`,
emp.`ename`,
emp.`salary`,
job.`jname`,
job.`description`
FROM
emp,
job
WHERE emp.`job_id` = job.`id`;

-- 2. 查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
SELECT
emp.`id`,
emp.`ename`,
emp.`salary`,
job.`jname`,
job.`description`,
dept.`dname`,
dept.`loc`
FROM
emp,
job,
dept
WHERE emp.`dept_id` = dept.`id` AND emp.`job_id` = job.`id`;

-- 3. 查询员工姓名,工资,工资等级
SELECT
t1.`ename`,
t1.`salary`,
t2.`grade`
FROM
emp t1,
salarygrade t2
WHERE t1.`salary` BETWEEN t2.`losalary`
AND t2.`hisalary`;

-- 4. 查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
SELECT
t1.`ename`,
t1.`salary`,
t3.`jname`,
t3.`description`,
t2.`dname`,
t2.`loc`,
t4.`grade`
FROM
emp t1,
dept t2,
job t3,
salarygrade t4
WHERE t1.`job_id` = t3.`id`
AND t1.`dept_id` = t2.`id`
AND t1.`salary` BETWEEN t4.`losalary`
AND t4.`hisalary`;


-- 5. 查询出部门编号、部门名称、部门位置、部门人数
SELECT
t2.`id`,
t2.`dname`,
t2.`loc`,
COUNT(t1.`id`) AS ' 部门人数 '

FROM
emp t1,
dept t2
WHERE
t1.`dept_id` = t2.`id`
GROUP BY
t1.`dept_id`;

-- 使用子查询的结果是多行多列的, 可以作为一张「虚拟表」参与查询
SELECT
t2.`id`,
t2.`dname`,
t2.`loc`,
t1.` 部门人数 `
FROM
(SELECT
dept_id,
COUNT (id) AS " 部门人数 "
FROM
emp
GROUP BY emp.`dept_id`) AS t1,
dept AS t2
WHERE t1.`dept_id` = t2.`id`;

-- 6. 查询所有员工的姓名及其直接上级的姓名, 没有领导的员工也需要查询
SELECT
t1.`ename` AS " 员工姓名 ",
t2.`ename` AS " 直接上级 "
FROM
emp t1 -- emp t1, emp t2 成为「自相关」
LEFT JOIN emp t2 -- 查询左表的数据和其交集的数据, 左外连接
ON t1.`mgr` = t2.`id`;

事务

事务的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1. 事务的基本介绍 
1. 概念:
* 如果一个包含多个步骤的业务操作「被事务管理」,那么这些业务操作要么同时成功,要么同时失败。

2. 操作:
1. 开启事务: START TRANSACTION;
2. 回滚: ROLLBACK;
3. 提交: COMMIT;

3. MySQL 数据库中事务默认自动提交

* 事务提交的两种方式:
* 自动提交:
* MySQL 数据库默认是自动提交事务
* 一条 DML(增删改) 语句会自动提交一次事务
* 手动提交:
* Oracle 数据库默认是手动提交事务
* 需要先开启事务,再提交
* 修改事务的默认提交方式:
* 查看事务的默认提交方式: SELECT @@autocommit; -- 1 代表自动提交 0 代表手动提交
* 修改默认提交方式: set @@autocommit = 0;

四大特性和隔离级别

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2. 事务的四大特征:
1. 原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。
2. 持久性:当事务提交或回滚后,数据库会持久化的保存数据。
3. 隔离性:多个事务之间相互独立。
4. 一致性:事务操作前后,数据总量不变。

3. 事务的隔离级别(了解)
* 概念: 多个事务之间隔离的、相互独立的,但是如果多个事务操作同一批数据,则会引发一些问题,
设置不同的隔离级别就可以解决这些问题。
* 存在的问题:
1. 脏读:一个事务读取到另一个事务中没有提交的数据
2. 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。
3. 幻读:一个事务操作(DML 操作) 数据表中所有记录,另一个事务添加了一条数据,
则第一个事务查询不到自己的修改。
* 隔离级别:
1. read uncommitted:读未提交
* 会产生的问题:脏读、不可重复读、幻读
2. read committed:读已提交 (Oracle 默认)
* 会产生的问题:不可重复读、幻读
3. repeatable read:可重复读 (MySQL 默认)
* 会产生的问题:幻读
4. serializable:串行化
* 可以解决所有的问题
* 注意:隔离级别从小到大安全性越来越高,但是效率越来越低

* 数据库查询隔离级别:
* SELECT @@tx_isolation;
* 数据库设置隔离级别:
* SET GLOBAL TRANSACTION ISOLATION LEVEL 级别字符串;

* 演示:
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
-- 转账操作
UPDATE account SET balance = balance - 500 WHERE id = 1;
UPDATE account SET balance = balance + 500 WHERE id = 2;

ROLLBACK; -- 回滚
COMMIT; -- 提交

DCL:数据控制语句

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
* SQL 分类:
1. DDL:操作数据库和表
2. DML:增删改表中数据
3. DQL:查询表中数据
4. DCL(Data Control Language):管理用户,授权

* DCL:管理用户,授权
1. 管理用户
1. 添加用户:
* 语法: CREATE USER ' 用户名 '@' 主机名 ' IDENTIFIED BY ' 密码 ';
2. 删除用户:
* 语法: DROP USER ' 用户名 '@' 主机名 ';
3. 修改用户密码:
* 语法: UPDATE USER SET PASSWORD = PASSWORD(' 新密码 ') WHERE USER = ' 用户名 ';
* 语法: SET PASSWORD FOR ' 用户名 '@' 主机名 ' = PASSWORD(' 新密码 ');

* mysql 中忘记了 root 用户的密码?
1. cmd --> net stop mysql 停止 mysql 服务(需要管理员运行该 cmd)
2. 使用无验证方式启动 mysql 服务, 命令: mysqld --skip-grant-tables
3. 打开新的 cmd 窗口, 直接输入 mysql 命令, 敲回车, 就可以登录成功
4. 输入命令: USE mysql;
5. UPDATE USER SET PASSWORD = PASSWORD(' 新密码 ') WHERE USER = 'root';
6. 关闭两个窗口后, 打开任务管理器, 手动结束 mysqld.exe 的进程
7. 启动 mysql 服务, 使用新密码登录
4. 查询用户:
-- 1. 切换到 mysql 数据库
USE myql;
-- 2. 查询 user 表
SELECT * FROM USER;

2. 权限管理:
1. 查询权限:
-- 查询权限
SHOW GRANTS FOR ' 用户名 '@' 主机名 ';
* 通配符: % 表示可以在任意主机使用用户登录数据库

2. 授予权限:
-- 授予权限
GRANT 权限列表 ON 数据库名. 表名 TO ' 用户名 '@' 主机名 ';
-- 给张三用户授予所有权限(ALL), 在任意数据库上操作任意表(*.*)
GRANT ALL ON *.* TO 'zhangsan'@'localhost';
-- 刷新使授权立即生效
flush privileges;
3. 撤销权限:
-- 撤销权限:
revoke 权限列表 on 数据库名. 表名 from ' 用户名 '@' 主机名 ';
REVOKE UPDATE ON db3.`account` FROM 'lisi'@'%';

数据库管理软件分类

管理数据的工具根据它们存取数据的特点来划分,主要分为关系型和非关系型。可以简单的理解为,关系型数据库需要有表结构 *,* 非关系型数据库是 key-value 存储的,没有表结构。

MySQL 是一种关系数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。

存储引擎

存储引擎:存储数据的方式

  • InnoDB 存储引擎(数据持久化):MySQL5.6 之后的默认的存储引擎

  • Myisam 存储(数据持久化):MySQL5.5 之前的默认存储引擎。

  • Memory 存储引擎(断点数据消失):数据存储在内存中,也就是说数据断点消失

InnoDB 存储引擎:共 2 个文件,数据和索引存储在一起,即数据、索引一个文件,表结构一个文件。原子性操作:不能再拆分。查看当前默认的存储引擎:show variables like %engin%;

  • Innodb 存储引擎:支持事务、支持行级锁、表级锁、支持外键。
  • 支持事务:为了保证数据的完整性,将多个操作变成原子性操作,保证数据安全。
  • 支持行级锁:修改的行少的时候用,适合修改数据频繁的操作。
  • 表级锁:批量修改多行的时候用,适合对于大量数据的同时修改。
  • 支持外键:约束两张表中的关联字段不能随意的添加和删除,降低数据增删改的出错率。
1
2
3
4
5
6
7
# 面试题:
# 了解 mysql 的存储引擎吗? Innodb Myisam Memory
# 项目用了什么存储引擎,为什么?
# innodb, 因为 innodb 存储引擎: 支持事务,行锁,表锁,外键。
# 因为,多个用户操作的过程中对同一张表的数据同时做修改,innodb 支持行级锁,所以用了这个存储引擎。
# 为了适应程序未来的扩展,扩展新功能的时候可能会用到,涉及要维护的数据的完整性。
# 项目中有两张表,之间的外键关系是什么···,一张表的修改或删除比较频繁,怕出错所以做了外键约束。

多表结构的创建与分析

如何找出两张表之间的关系

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
26
27
28
29
30
31
分析步骤:
1、先站在左表的角度去找
是否左表的多条记录可以对应右表的一条记录,
如果是,则证明左表的一个字段 foreign key 右表一个字段 (通常是 id)

2、再站在右表的角度去找
是否右表的多条记录可以对应左表的一条记录,
如果是,则证明右表的一个字段 foreign key 左表一个字段 (通常是 id)

3、总结:
# 多对一:
如果只有步骤 1 成立,则是左表多对一右表
如果只有步骤 2 成立,则是右表多对一左表

# 多对多:
如果步骤 1 和 2 同时成立,则证明这两张表时一个双向的多对一,即多对多。
此时,需要定义一个这两张表的关系表来专门存放二者的关系。

# 一对一:
如果 1 和 2 都不成立,即是左表的一条记录唯一对应右表的一条记录,反之亦然。
这种情况很简单,就是在左表 foreign key 右表的基础上,将左表的外键字段设置成 unique 即可。
create table customer(
id int primary key auto_increment,
name varchar(20) not null
);
create table student(
id int primary key auto_increment,
class_name varchar(20) not null,
customer_id int unique, -- 外键的字段一定要保证 unique
foreign key(customer_id) references customer(id)
);

数据类型

字符串类型

CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。

  • CHAR 最大长度为 255,尾部空格被抛弃,VARCHAR 最大长度 65535,尾部空格被保留。

BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串 。也就是说,它们 包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。

ENUM 和 SET 类型

ENUM 中文名称叫枚举类型,它的值范围需要在创建表时通过枚举方式显示。ENUM只允许从值集合中选取单个值,而不能一次取多个值

SET 和 ENUM 非常相似,也是一个字符串对象,里面可以包含 0-64 个成员。根据成员的不同,存储上也有所不同。set 类型可以 允许值集合中任意选择 1 或多个元素进行组合。对超出范围的内容将不允许注入,而对重复的值将进行自动去重。

类型 大小 用途
ENUM 对 1-255 个成员的枚举需要 1 个字节存储;对于 255-65535 个成员,需要 2 个字节存储;最多允许 65535 个成员。 单选:选择性别
SET 1-8 个成员的集合,占 1 个字节;9-16 个成员的集合,占 2 个字节;17-24 个成员的集合,占 3 个字节;25-32 个成员的集合,占 4 个字节;33-64 个成员的集合,占 8 个字节。 多选:兴趣爱好

外键与 innoDB 存储引擎

外键 foreign key 约束:具有外键的表的存储引擎必须是 innoDB 存储引擎,且被关联的字段(即 references 指定的另一张表的字段)必须保证唯一。具有外键的表的记录,随与之关联的父表的记录同步更新on update cascade、同步删除on delete cascade

1
2
3
4
5
6
7
create table father_table(
...
)engine = innodb;

create table child_table(
...
)engine = innodb;

MySQL 索引原理

索引的设计,可以加快查询速度。

case when then 用法

case 具有两中格式:简单 case 函数和 case 搜索函数。case 函数只返回第一个符合条件的值,剩下的 case 部分将会被自动忽略。

Tip:case when then 得到的结果是「多行一列」的,得到后可以继续对其使用聚合函数。

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
26
27
28
-- 简单 case 函数
case sex
when '1' then ' 男 '
when '2' then ' 女 '
else ' 其他 ' end;

-- case 搜索函数
case
when sex = '1' then ' 男 '
when sex = '2' then ' 女 '
else ' 其他 ' end;


-- 将性别 id 替换为可读的中文
SELECT u.id, u.name,
(CASE u.sex
WHEN 1 THEN ' 男 '
WHEN 2 THEN ' 女 '
ELSE ' 空的 ' END
) ' 性别 '
FROM users u;

-- 统计不同性别的人的数量
SELECT
COUNT(CASE WHEN u.sex=1 THEN 1 END) 'male',
COUNT(CASE WHEN u.sex=2 THEN 1 END) 'female',
COUNT(CASE WHEN u.sex <>1 AND u.sex<>2 THEN 1 END) 'other'
FROM users u;

select into

INSERT INTO 语句用于向表格中插入新的行。

SELECT INTO 语句从一个表中选取数据,然后 把数据插入另一个表中 常用于创建表的备份复件或者用于对记录进行存档

1
2
3
4
5
6
7
8
9
10
11
12
-- 指定所要插入数据的列:
INSERT INTO table_name (列 1, 列 2,...) VALUES (值 1, 值 2,....)

-- 把所有的列插入新表
SELECT *
INTO new_table_name [IN externaldatabase]
FROM old_tablename

-- 只把希望的列插入新表
SELECT column_name1, column_name3
INTO new_table_name [IN externaldatabase]
FROM old_tablename

delect 与 truncate 比较

  • 处理效率:drop > truncate > delete。
  • drop 删除整个表;truncate 删除全部记录,但不删除表(的结构);delete 删除部分记录。
  • delete 不影响所用 extent,高水线保持原位置不动;truncate 会将高水线复位