MySQL数据库学习
如果想更多学习更多知识,无论是哪种语言、哪种教程,建议收藏下面网站,这里面是真的全:
http://c.biancheng.net/
系列文章目录
- MySQL数据库学习
- 前言
- MySQL的安装配置
- 数据库概述
- SQL数据库的命令
-
- SQL的特点
- 创建并使用数据库
- 添加数据
- 插入数据
- ---
- 删除数据库
- 删除表
- 删除语句
- 删除数据
- ---
- 修改数据库
- 修改表
- 修改表的约束
- 修改数据
- ---
- 查询语句格式
- 多重条件查询
- 分组查询(GROUP BY 子句)
- 聚集函数
- 单表查询
- 嵌套子查询
- 子查询
- 比较运算中使用子查询
- 各种子查询
- 带有IN的子查询
- SOME(子查询)
- ALL(子查询)
- EXISTS子查询
- 复杂查询UNION [ALL]
- 小结:SELECT 的基本结构
- ---
- SQL的组成部分
- SELECT后面直接跟列名
- DISTINCT关键字
- 列更名
- WHERE子句
- 范围比较:BETWEEN … AND …
- 比较运算
- 集合查询:IN
- 空值比较:IS NULL
- 字符串模糊查询:LIKE
- LIKE的用法
- ORDER BY子句:排序
- 小结:SELECT 的基本结构
- ---
- 多表连接查询
- 给表起别名
- 自连接
- 表连接的语法格式
- 表内连接的语法格式
- 内连接的特点:
- 表外连接
- 左外连接
- 右外连接
- 全外连接
- 数据库的视图与索引
- 数据库设计
- 数据库的备份与恢复
前言
本人会用几天时间把数据库知识总结一下,希望大家三连好评,感谢!
数据库规范的写法是要大写,但运行起来小写也一样,只要能记住语法
就学会了一大半
MySQL的安装配置
MySQL软件下载安装配置——详细教程(软件)
MySQL软件下载安装配置——详细教程(命令行)
数据库概述
SQL数据库的命令
下面的命令基本上是想到哪写到哪,没有什么顺序可言
SQL的特点
(1)功能一体化
(2)高度非过程化
(3)面向集合的操作方式
(4)两种使用方式:命令行和嵌入到其他宿主语言(如Java等)方式
(5)简洁易学
(6)大大减轻了用户的负担,并有利于提高数据独立性
(7)非关系数据模型采用的是面向记录的操作方式,操作对象是一条记录。而SQL采用集合操作方式,其查找对象查找结果都是数据的集合,每次插入删除更新操作的对象也是数据的集合。这种操作方式极大的提高了数据操作的效率。
(8)SQL语言可以直接以命令方式与数据库进行交互,也可以作为嵌入式语言嵌入到其他程序设计语言(如Java、C等)中,并且两种不同使用方式中SQL语言的语法结构基本上是一致的。
创建并使用数据库
创建数据库CREATE DATABASE 数据库名
使用数据库use 数据库名;
添加数据
前面的添加数据命令一次只能插入一条记录。如果想一次插入多条记录怎么办呢?
可以将子查询的结果,以集合的方式向表中添加数据。
格式:INSERT INTO <表名> 子查询
【例】创建一个新表‘清华大学出版图书表’并将清华大学出版社出版的图书添加到此表中。
CREATE TABLE thboPRIMARY KEY,
name VARCHAR(30) ,
author VARCHAR(10),
publish VARCHAR(20),
price DECIMAL(6,2)
)
INSERT INTO thbook
SELECT * FROM Book WHERE publish='清华大学出版社'
插入数据
INSERT语句的基本语法:
INSERT INTO 表名(列名列表)
VALUES(值列表)
注意:列名列表 与 值列表 永远保持一致!
【例】试把数据“(’021B310001’,’张冬’, ’男’, ’1991-11-26’)”插入到Reader表中。
INSERT INTO Reader(reader_ID,name,sex,birthdate)
VALUES('021B310001','张冬','男','1991- 11-26')
要插入的数据如果恰好与表的列数以及各列的顺序保持一致,所以“列名列表”也可以省略掉,变成如下的形式:
INSERT INTO Reader
VALUES('021B310001','张冬','男','1991-11-26')
【例】Reader表中插入下面的数据:
读者编号:’021B310002’
读者姓名:’牟晓光’
读者性别:’女’
INSERT INTO Reader(reader_ID,name,sex)
VALUES('021B310002','牟晓光','女')
或者:
INSERT INTO Reader
VALUES('021B310002','牟晓光','女',NULL)
—
删除数据库
删除数据库语句DROP DATABASE 数据库名
这条语句会删除数据库中的所有表格并同时删除数据库,当然你要删除的是数据库里存在的名字
被删除的数据库不能是当前正在使用的数据库。
使用数据库删除语句可以一次删除多个数据库。
【例】删除 “图书管理” 数据库:
DROP DATABASE 图书管理
【例】删除 MY1 和 MY2 数据库:
DROP DATABASE MY1, MY2
删除表
语法格式:DROP TABLE <表名>{[,<表名>]…}
【例】删除 "student "表
DROP TABLE student
注意:有外码参照的表只能在外码所在表删除后才可以被删除。
删除语句
语法格式:DELETE FROM 表名 WHERE 数据;
删除数据
语法格式:DELETE FROM <表名> [ WHERE <删除条件> ]
【例】删除Book表中的全部数据
DELETE FROM Book
【例】删除价格大于100元的图书
DELETE FROM Book WHERE price>100
【例】删除王旭的借阅纪录
子查询方式实现
DELETE FROM Borrow WHERE Reader_id IN
(SELECT Reader_id FROM Reader WHERE name='王旭')
—
修改数据库
语法格式:
ALTER DATABASE 数据库名 {
[ DEFAULT ] CHARACTER SET <字符集名> |
[ DEFAULT ] COLLATE <校对规则名>}
修改表
语法格式:
ALTER TABLE <表名>
{[ ALTER COLUMN <列名> <新数据类型>] -- 修改列定义
| [ ADD <列名> <数据类型> [约束] ] -- 添加新列
| [ DROP COLUMN <列名> ] } -- 删除列
修改表中列示例
【例】为student表添加 “班级” 列,列的定义为 class CHAR(30)
ALTER TABLE student ADD class CHAR(30)
【例】将class列修改为 VARCHAR(30)
ALTER TABLE student ALTER COLUMN class VARCHAR(30)
【例】删除class列
ALTER TABLE student DROP COLUMN class
【例】为Reader表添加"职业"列,列的定义为 profession CHAR(20)
ALTER TABLE Reader
ADD profession CHAR(20)
【例】将profession列修改为char(30)
ALTER TABLE Reader
ALTER COLUMN profession CHAR(30)
【例】删除profession列
ALTER TABLE Reader
DROP COLUMN profession
修改表的约束
语法格式:
ALTER TABLE <表名>
{ [ ADD CONSTRAINT <约束名> <约束> ]
-- 给表添加新约束
| [ DROP CONSTRAINT <约束名> ] }
-- 删除表中某约束
修改表中约束示例
【例】为Reader表Sex列添加检查约束 chk_sex,限制该列输入值只能为“男” 或 “女”
ALTER TABLE Reader
ADD CONSTRAINT chk_sex
CHECK(Sex='男' OR Sex='女');
【例】给Borrow表添加检查约束chk_date,使得还书日期要大于借书日期。
ALTER TABLE Borrow
ADD CONSTRAINT chk_date
CHECK(returndate>borrowdate);
【例】删除Reader表上的约束chk_sex。
ALTER TABLE Reader
DROP CONSTRAINT chk_sex;
修改数据
语法:
UPDATE <表名>
SET <列名=值|表达式>[,…]
[WHERE <更新条件>]
【例】所有图书的价格打8折
UPDATE Book SET price = price*0.8
更新前
更新后
练习
使用library数据库,把王旭的出生日期改成1995-3-2
update reader set birthdate='1995-3-2'
where name='王旭'
修改reader表中为021B310005的读者的名字改为宋玮凌,性别改为男
update Reader set name='宋玮凌',sex='男'
where Reader_ID='021B310005'
【例】将王旭所借图书的日期更改为2022-5-1
子查询方式
UPDATE Borrow SET Borrowdate= '2022-5-1'
WHERE reader_ID IN
(SELECT reader_ID FROM Reader
WHERE name= '王旭')
更改‘胡晓丽’借阅‘高等数学’的借阅日期为‘2022-6-8’
UPDATE Borrow SET Borrowdate= '2022-6-8’
WHERE reader_ID IN
(SELECT reader_ID FROM Reader
WHERE name= '胡晓丽')
and book_ID IN
(SELECT book_ID FROM book
WHERE name= '高等数学')
—
查询语句格式
SELECT [ALL|DISTINCT] <目标列名序列>
FROM <数据源>
[ WHERE <检索条件表达式> ]
[ GROUP BY <分组依据列>
[ HAVING <组提取条件表达式> ] ]
[ ORDER BY <排序依据列> [ ASC|DESC ] ]
查询仅涉及一张表
SELECT子句:选择表中列
WHERE子句:筛选表中元组
ORDER BY子句:对查询结果排序
聚集函数:统计
GROUP BY子句:分组查询
HAVING子句:对分组结果筛选
多重条件查询
【例】查询1992年以后出生的女读者的姓名
SELECT name FROM Reader
WHERE birthdate >= '1992-1-1' AND sex='女'
分组查询(GROUP BY 子句)
【例】统计每个出版社的出版图书的数目
分析:如果能够将所有的图书,按照出版社的名称进行分组,然后我们在统计每一组的元组的个数,我们就能能到得到期望的数据。如图:
Book_ID | Name | Author | Public | Price | |
---|---|---|---|---|---|
1 | 256B10001 | 数据库原理 | 张三 | 电子工业出版社 | 25.00 |
2 | 256B10001 | 离散数学 | NULL | 高等教育出版社 | 28.00 |
3 | 256B10001 | 线形数学 | 李四 | 高等教育出版社 | 51.00 |
4 | 256B10001 | 大学语文 | 张龙 | 机械工业出版社 | 31.00 |
5 | 256B10001 | C语言 | 赵虎 | 机械工业出版社 | 22.00 |
6 | 256B10001 | JAVA | 王朝 | 清华大学出版社 | 42.00 |
7 | 256B10001 | Python | 马汉 | 清华大学出版社 | 21.00 |
可以使用GROUP BY <列名>进行分组
在<列名>上值相同的元组被分在一组,该列称为分组依据列。然后可以使用聚集函数统计每一组的数据。
SELECT COUNT(*) , publish FROM Book
GROUP BY publish
【例】统计每个人所借图书的数目。
SELECT COUNT(book_ID), Reader_id
FROM Borrow
GROUP BY Reader_id
Having COUNT(book_ID)>2
【例】统计每个出版社出版图书的平均价格,并显示每个出版社的名称
SELECT publish, AVG(price) AS 平均价格
FROM Book
GROUP BY publish
【例】查询出版图书平均价格高于30元的出版社名称,并显示其图书平均价格。
HAVING 子句用于对分组统计后的结果进行筛选。满足HAVING 子句条件将会保留在结果中
SELECT publish,AVG(price) FROM Book
GROUP BY publish
HAVING AVG(price)>30
【例】查询出版图书多于2本的出版社名称和出版图书数目
SELECT publish, COUNT(*) FROM Book
GROUP BY publish
HAVING COUNT(*)>2
聚集函数
聚集函数(也叫集合函数),方便统计一些数据。
COUNT ( * ): 统计表中元组个数;
COUNT (列名 ):统计本列列值个数;
SUM (列名 ):计算列值总和(必须是数值型列);
AVG (列名 ):计算列值平均值(必须是数值型列);
MAX (列名 ):求列值最大值;
MIN (列名 ):求列值最小值。
【例】统计全部图书的平均价格
SELECT AVG(price) FROM Book
【例】查询最高的图书价格
SELECT MAX(price) FROM Book
【例】统计读者的总人数
SELECT COUNT(*) FROM Reader
单表查询
查询语句格式
SELECT [ALL|DISTINCT] <目标列名序列>
FROM <数据源>
[ WHERE <检索条件表达式> ]
[ GROUP BY <分组依据列>
[ HAVING <组提取条件表达式> ] ]
[ ORDER BY <排序依据列> [ ASC|DESC ] ]
嵌套子查询
思考:查询和王旭同一天出生的读者的信息
分析:查询王旭的生日
SELECT birthdate FROM Reader WHERE name='王旭'
那么可不可以使用这个查询结果呢?当然可以!
SELECT * FROM Reader WHERE birthdate=(
SELECT birthdate FROM Reader WHERE name='王旭')
子查询
在SQL语言中,一个SELECT-FROM语句称为一个查询块。
如果一个SELECT语句嵌套在另一个SELECT、INSERT、UPDATE或DELETE语句中,则称之为子查询或内层查询;而包含子查询的语句则称为主查询或外层查询。
执行顺序:先内层后外层;先子查询后主查询
比较运算中使用子查询
【例】查询售价最高的图书的名称
SELECT name FROM Book WHERE price=(SELECT MAX(price) FROM Book)
【例】查询图书价格在25到50元之间的图书
SELECT * FROM Book
WHERE price BETWEEN 25 AND 50
• 等价于:
SELECT * FROM Book
WHERE price>=25 AND price <=50
各种子查询
子查询返回结果只有一个值 | 子查询返回多个值 | |
---|---|---|
等值比较 | =、< >判断可以用in代替 | 采用 in或 not in进行判断 |
不等比较 | >、<、>=、<= | >、<、>=、<= ALL some |
带有IN的子查询
【例】查询与"C语言"在同一出版社的图书信息
SELECT * FROM Book WHERE publish IN (
SELECT publish FROM Book WHERE name='C语言')
【例】查询王旭所借图书的图书编号
Reader_ID | Reader | sex | birthdate |
---|---|---|---|
021B310003 | 于大海 | 男 | 1992-01-26 |
021B310013 | 张三春 | 女 | 1991-01-12 |
021B310104 | 李四 | 男 | 1992-02-28 |
021B310105 | 王海旭 | NULL | 1997-07-08 |
021B310006 | 王五 | 男 | 1992-08-23 |
021B310008 | 赵六 | 女 | NULL |
book_ID | Reader_ID | Borrowdate |
---|---|---|
A32DT0003 | 021B310003 | 2022-05-12 |
A32DT0005 | 021B310013 | 2022-06-27 |
A32DT0013 | 021B310104 | 2022-08-03 |
A32DT0011 | 王海旭 | 2022-02-24 |
A32DT1004 | 王五 | 2022-08-19 |
A32DT0109 | 赵六 | 2022-08-08 |
SELECT book_ID FROM Borrow WHERE reader_ID IN (
SELECT reader_ID FROM Reader WHERE
name='王旭')
【例】查询"王旭"所借的图书的名称
SELECT name FROM Book WHERE book_ID IN
(SELECT book_ID FROM Borrow WHERE reader_ID IN (SELECT reader_ID FROM Reader WHERE name='王旭') )
查询过程:
第1步,查询"王旭"的reader_ID。
第2步,依据reader_ID在Borrow表中找王旭所借图书的book_ID
第3步,依据book_ID在Book表中找到图书名称。
查询借书价格在20-40之间的读者的姓名
select name from reader where reader_id in
(select reader_id from borrow where book_id in
(select book_id from book where price between 20 and 40))
查询胡晓丽 ‘借阅’ 计算机文化基础’的日期
select borrowdate from borrow where reader_id in(
select reader_id from reader where name='胡晓丽')
and book_id in(
select book_id from book where name='计算机文化基础')
查询借书价格在20-40之间的读者的姓名
select name from reader where reader_id in
(select reader_id from borrow
where book_id in
(select book_id from book
where price between 20 and 40
)
)
SOME(子查询)
表示子查询的结果集合中某一个元素
【例】查询除最低价格外的所有图书
SELECT * FROM Book WHERE
price!=(SELECT min(price) FROM Book)
或
SELECT * FROM Book WHERE
price>SOME(SELECT price FROM Book)
【例】查询价格最低的图书信息
SELECT * FROM Book WHERE
price=(SELECT min(price) FROM Book)
或
SELECT * FROM Book WHERE NOT(
price>SOME(SELECT price FROM Book))
ALL(子查询)
表示子查询的全部结果
【例】查询书价最高的图书的信息
SELECT * FROM Book WHERE
price=(SELECT max(price) FROM Book)
或
SELECT * FROM Book WHERE
price >=ALL(SELECT price FROM Book)
EXISTS子查询
判断子查询是否存在结果
当子查询存在结果时,EXISTS(子查询)返回值为true,否则返回值为false。
先外层查询,后内层查询;将外层的值代入内层进行查询,根据内层查询是否存在结果,判断外层的元组是否保留在结果集中。
【例】查询借阅了图书的读者的姓名
SELECT name FROM reader WHERE
EXISTS ( SELECT * FROM borrow WHERE
borrow.reader_id=reader.reader_id)
【例】查询被借出的图书的信息
SELECT * FROM Book WHERE EXISTS
(SELECT * FROM Borrow WHERE Borrow.book_ID=Book.book_ID)
复杂查询UNION [ALL]
使用UNION语句可以合并两个或多个查询的结果。
UNION语句用第二个查询结果合并第一个查询结果。
它不显示两个查询中的重复的行。
如果想显示所有行(包括重复行)则可以在UNION后面添加ALL谓词
UNION的语法格式:
SELECT <目标列名序列>
FROM <数据源>
[WHERE <检索条件表达式>]
[GROUP BY <分组依据列>]
[HAVING <组提取条件>]
UNION [ALL]
SELECT <目标列名序列>
FROM <数据源>
[WHERE <检索条件表达式>]
[GROUP BY <分组依据列>]
[HAVING <组提取条件>]
[ORDER BY <排序依据列>]
注意:如果使用使用ORDER BY 字句进行排序,则该子句只出现最后一个查询的后面,如果不希望去除重复的元组,可以使用关键字ALL。
• 【例】
SELECT * FROM Book
WHERE publish='清华大学出版社'
UNION SELECT * FROM Book WHERE price<25
• 【例】
SELECT * FROM Book
WHERE publish='清华大学出版社' UNION ALL
SELECT * FROM Book WHERE price<25
ORDER BY name
小结:SELECT 的基本结构
SELECT <目标列名序列> —— 查询哪些列
FROM <数据源> —— 来自于哪些表
[WHERE <检索条件表达式>] —— 筛选的条件
[GROUP BY <分组依据列>] ——根据那些列分组
[HAVING <组提取条件>] ——分组后的筛选条件
[ORDER BY <排序依据列>] ——根据那些列排序
—
SQL的组成部分
SQL功能 | 命令 |
---|---|
数据定义语言( Data Definition Language,简称DDL) | create、alter |
数据操纵语言( Data Manipulation Language,简称DML) | insert、delete、update、select |
数据控制语言( Data ControlLanguage,简称DCL) | grant、revoke |
SELECT后面直接跟列名
name | author | price | |
---|---|---|---|
1 | 计算机文化基础 | 张三 | 28.00 |
2 | C语言 | 李四 | 58.00 |
3 | JAVA | 王五 | 25.00 |
4 | Python | 赵六 | 27.00 |
【例】查询Book表中的书名(name),作者(author),价格(price)
SELECT name, author, price FROM Book
【例】查询Book表中的全部数据
select * from book
DISTINCT关键字
如果在结果中重复的数据不想显示出来,可以使用DISTINCT关键字
对比结果:
【例】
SELECT pubilsh FROM Book
对比:
SELECT DISTINCT pubilsh FROM Book
【例】查询每一本书九折后的价格
book_ID | name | price | |
---|---|---|---|
1 | A025B1 | 计算机文化基础 | 28.00 |
2 | A025B2 | C语言 | 58.00 |
3 | A025B3 | JAVA | 25.00 |
4 | A025B4 | Python | 27.00 |
SELECT book_ID,name,price*0.9 FROM Book
列更名
SQL 提供了为关系表和属性重新命名的机制。
首先来学习一下如何为列重命名。经过计算的列、函数的列和常量列的显示结果都没有列名,也可以通过这样的方式指定列名。
语法格式:旧列名 | 表达式 [ AS ] 新列名 或:新列名 =旧列名 | 表达式
WHERE子句
语法格式:
SELECT 列名列表 FROM 表名
WHERE 条件表达式
【例2.25】查询价格大于30元的图书的全部信息
SELECT * FROM Book WHERE price >30
WHERE子句中可以使用的查询条件
范围比较:BETWEEN … AND …
【例】查询图书价格在25到50元之间的图书
SELECT * FROM Book
WHERE price BETWEEN 25 AND 50
等价于
SELECT * FROM Book
WHERE price>=25 AND price <= 50
【例】图书价格不在20到30元之间的图书
SELECT * FROM Book
WHERE price NOT BETWEEN 20 AND 30
等价于
SELECT * FROM Book
WHERE price<20 OR price >30
比较运算
【例】查询所有的女读者的信息
Select * from reader where sex='女'
【例】查询图书价格在30到50元之间的图书
SELECT * FROM Book WHERE price BETWEEN 25 AND 50
【例】查询“机械工业出版社”或者“清华大学出版社”出版的图书
SELECT * FROM Book WHERE publish ='机械工业出版社' or publish = '清华大学出版社','高等教育出版社'
集合查询:IN
【例】查找“机械工业出版社”,“清华大学出版社”,“高等教育出版社”出版的全部图书
SELECT * FROM Book
WHERE publish IN('机械工业出版社','清华大学出版社','高等教育出版社')
【例】查找不是“机械工业出版社”,“清华大学出版社”,“高等教育出版社”出版的全部图书
SELECT * FROM Book
WHERE publish NOT IN ('机械工业出版社','清华大学出版社','高等教育出版社')
空值比较:IS NULL
【例】查询性别为空的读者的信息
SELECT * FROM Reader
WHERE sex IS NULL
【例】查询出生日期不为空的读者的姓名
SELECT name FROM Reader
WHERE birthdate IS not NULL
字符串模糊查询:LIKE
Reader_ID | name | sex | birthdate | |
---|---|---|---|---|
1 | 256B10001 | 张三春 | NULL | 1992-07-13 |
2 | 256B10002 | 李四 | 女 | 1992-07-18 |
【例】查询姓全部 “张” 的读者的信息。
SELECT * FROM Reader
WHERE name LIKE '张%'
LIKE的用法
列名 LIKE <字符串>
在字符串中我们可以使用通配符
_
代表任意一个字符
%
代表任意多个字符
ORDER BY子句:排序
ORDER BY <列名> [ASC|DESC][,…n]
ASC表示升序排序;DESC表示降序排序
默认情况为升序排序
• 注:对于空值,若按照升序排序,含空值的元组将最后
显示。若按降序排序,空值的元组将最先显示
Reader_ID | name | sex | birthdate | |
---|---|---|---|---|
1 | 256B10001 | 张三春 | NULL | 1992-07-13 |
2 | 256B10002 | 李四 | 女 | 1992-07-18 |
3 | 256B10003 | 王五 | NULL | 1991-01-18 |
4 | 256B10004 | 赵六 | 男 | 1992-08-18 |
5 | 256B10005 | 张一龙 | 女 | 1992-08-03 |
【例】查询读者的信息按出生日期的升序显示
SELECT * FROM Reader
ORDER BY birthdate ASC
【例】查询读者的信息按出生日期的
SELECT MAX(price) FROM Book
"降序"显示
SELECT * FROM Reader
ORDER BY birthdate DESC
【例】查询图书的信息,查询结果按照出版社的名称升序排序,同一出版社的按照价格的降序排序。
SELECT * FROM Book
ORDER BY publish ASC,price DESC
小结:SELECT 的基本结构
SELECT <目标列名序列> – 查询哪些列
FROM <数据源> – 来自于哪些表
[WHERE <检索条件表达式>] – 筛选的条件
[GROUP BY <分组依据列>] --根据那些列分组
[HAVING <组提取条件>] --分组后的筛选条件
[ORDER BY <排序依据列>] --根据那些列排序
—
多表连接查询
1、表连接的语法格式
FROM 表1 [inner|outer] JOIN 表2
ON <连接条件>
其中表1,表2是需要连接的两张表, JOIN 表示连接,inner表示内连接,outer表示外连接,缺省情况就是内连接。
ON后面接<连接条件>
2、表内连接的语法格式
FROM 表1 [inner] JOIN 表2 ON <连接条件>
• 连接条件的一般格式为:
[<表名1.>][<列名1>] <比较运算符> [<表名2.>][<列名2>]
两个表的连接列必须是可比较的,即是语义相同的列,否则比较将是无意义的。
当比较运算符为等号(=)时,称为等值连接,使用其他运算符的连接称为非等值连接。
给表起别名
在SQL语句中,可以类似为列取别名那样为表取别名,
格式:
<源表名> [ AS ] <表别名>
• 注意:当为表指定了别名时,在查询语句中的其他地方,所有用到表名的地方都要使用别名,不能再使用原表名。
• 【例】查询 ‘王旭’ 所借图书的书名
SELECT B.name FROM Book B JOIN Borrow W
ON B.book_ID=W.book_ID JOIN Reader R ON
R.Reader_id=W.Reader_id WHERE R.name='王旭'
自连接
一张表和自身连接。必须给表其别名
• 【例】查询与C语言在同一出版社的图书信息
分析:C语言一书在Book表中,与它在同一出版社的图书也在Book表中。二者通过publish相等进行连接
SELECT BookW.* FROM Book BookC JOIN
Book BookW on
BookC.publish=BookW.publish WHERE
BookC.name=‘C语言’ AND BookW.name<> 'C语言'
• 内连接的特点:满足连接条件的元组保留到连接的结果中,其中存在不满足连接条件的元组会被舍弃。
表连接的语法格式
Select …… FROM 表1
JOIN 表2
ON <连接条件>
其中表1,表2是需要连接的两张表, JOIN 表示连接,inner表示内连接,outer表示外连接,缺省情况就是内连接。ON后面接<连接条件>。
【例】查询2020年1月20日借书的读者姓名和所借图书的编号
SELECT Name, book_ID
FROM Reader
JOIN Borrow
ON Reader.reader_ID =Borrow.reader_ID
WHERE borrowdate= '2022-9-20'
表内连接的语法格式
Select…FROM 表1
JOIN 表2
ON <连接条件>
连接条件的一般格式为:[<表名1.>][<列名1>] <比较运算符> [<表名2.>][<列名2>]
两个表的连接列必须是可比较的,即是语义相同的列,否则比较将是无意义的。
当比较运算符为等号(=)时,称为等值连接,使用其他运算符的连接称为非等值连接。
【例】查询王旭所借图书的书号和借阅时间
SELECT book_ID, borrowdate
FROM Reader
JOIN Borrow
ON Reader.Reader_id =Borrow.Reader_id
WHERE name='王旭'
【例】查询2020年6月7日借阅图书的读者姓名和所借图书名称
SELECT Reader.name, Book.name
FROM Book
JOIN Borrow
ON Book.book_ID=Borrow.Book_ID
JOIN Reader
ON Reader.reader_ID=Borrow.reader_ID WHERE borrowdate='2020-6-7'
【例】查询每个读者所借的图书的信息,要求显示读者姓名,图书名称,借出日期
SELECT Reader.name AS 姓名,Book.name AS 图书名称,
Borrow.Borrowdate AS 借出日期 FROM Reader
JOIN Borrow
ON Reader.Reader_id = Borrow.Reader_id JOIN Book
ON Borrow.book_ID=Book.book_ID
注意:多表的同名列前面必须加表名前缀
即:表名.列名
给表起别名
在SQL语句中,可以类似为列取别名那样为表取别名,格式:<源表名> [ AS ] <表别名>
注意:当为表指定了别名时,在查询语句中的其他地方,所有用到表名的地方都要使用别名,不能再使用原表名。
【例】查询’王旭’所借图书的书名
SELECT B.name FROM Book B
JOIN Borrow W
ON B.book_ID=W.book_ID
JOIN Reader R
ON R.Reader_id=W.Reader_id
WHERE R.name='王旭'
内连接的特点:
满足连接条件的元组保留到连接的结果中,其中存在不满足连接条件的元组会被舍弃。
表X和Y内连接结果
SELECT a, X.b, Y.b, c
FROM X
JOIN Y
ON X.b=Y.b
表外连接
和内连接相对的就是外连接。
外连接的特点:满足连接条件的元组保留到连接的结果中,其中不满足连接条件的元组也会显示到连接结果中。
外连接分类:
左外连接
FROM 表1 LEFT [OUTER] JOIN 表2
ON <连接条件>
【例】SELECT a, X.b, Y.b, c
FROM X
LEFT JOIN Y
ON X.b=Y.b
右外连接
FROM 表1 RIGHT [OUTER] JOIN 表2
ON <连接条件>
【例】SELECT a, X.b, Y.b, c
FROM X
RIGHT JOIN Y
ON X.b=Y.b
例:统计每个读者所借阅的图书的数量,要求显示读者姓名和借阅数量
SELECT name,COUNT(book_id)
FROM Reader
left JOIN Borrow
ON Reader.Reader_id =Borrow.Reader_id
group by Reader.Reader_id ,name
例:统计,每本书被借阅的次数,要求显示书名和被借阅的次数
SELECT name,COUNT(reader_id)
FROM book
left JOIN Borrow
ON book.book_id =Borrow. book_id
group by book.book_id ,name
全外连接
FROM 表1 FULL [OUTER] JOIN 表2
ON <连接条件>
• 【例】查询所有读者借阅情况(包括没借阅图书的读者),显示读者编号,读者姓名,图书编号和书名。
SELECT R.reader_ID, R.name, B.book_ID, B.name
FROM Reader AS R LEFT JOIN Borrow
AS BW
ON R.reader_ID=BW.reader_ID LEFT
JOIN Book AS B ON B.book_ID=BW.book_ID
数据库的视图与索引
数据库设计
数据库的备份与恢复
备份恢复概述
在数据库系统中,保证数据库可以由错误状态恢复到正确状态的机制,称为备份与恢复。
备份是指定期地对数据库中的数据进行拷贝(或称转储),形成冗余副本。.
恢复是指当数据库发生故障时,利用数据库备份形成的副本来恢复数据库,将数据库恢复到正确状态。
故障的种类
1. 事务内部故障
事务没有到达预期的终点
2. 系统故障
指系统停止运转而引发的故障, 如停电、CPU故障、操作系统崩溃等
3. 介质故障
硬盘上保存数据库中数据的磁道损坏
4. 计算机病毒
数据库备份
按照数据库备份规模的不同分类:
完全备份:
备份数据库中的全部信息,包括数据文件、日志文件、备份文件的存储位置信息以及数据库中的全部对象。
差异备份:
在前一次完全备份之后,对数据所做的修改进行备份,包括完全备份之后变化了的数据文件、日志文件以及数据库中其它被修改了的对象。
事务日志备份:
备份上次日志备份之后的日志记录。
文件和文件组备份:
对数据库中个别文件进行备份,通常用在超大型数据库中。
按照备份的状态分类:
联机备份是指在数据库正常使用的时候,还有用户连接到数据库的时候,对数据库进行备份 脱机备份是指数据库停下来,与所有用户都断开连接的时候,对数据库进行备份
数据库的恢复
根据数据库恢复的程度不同分类:
完全恢复:将数据库恢复到出现故障时刻的一致性状态。
不完全恢复:将数据库恢复到出现故障时刻之前的某个一致性状态。
日志文件
数据库的日志文件用来记录事务对数据库进行的更新操作(insert, update, delete),当数据库出现故障时,通过日志文件中的事务,可以完全恢复数据库。因此,又称为重做日志文件。
数据库操作的一个重要原则就是“先写日志文件,后写数据文件”。