MySQL是一个关系型数据库管理系统**,**由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
MySql基础学习
一、引言
1.1 现有的数据存储方式有哪些?
- Java程序存储数据(变量、对象、数组、集合),数据保存在内存中,属于瞬时状态存储。
- 文件(File)存储数据,保存在硬盘上,属于持久状态存储。
1.2 以上存储方式存在哪些缺点?
- 没有数据类型的区分。
- 存储数据量极小。
- 没有安全访问限制。
- 没有备份、恢复机制。
二、数据库
2.1 概念
数据库是按照数据接口来组织、存储和管理数据的仓库。是一个长期存储在计算机内的、有组织的、有共享的、统一管理的数据集合。
2.2 数据库的分类
- 网状结构数据库:美国通用电气公司IDS(Integrated Data Store),以节点形式存储和访问。
- 层次结构数据库:IBM公司IMS(Information Management System)定向有序的树状结构实现存储和访问。
- 关系结构数据库:Oracle、DB2、MySQL、SQL Server,以表格(Table)存储,多表间建立关联关系,通过分类、合并、连接、选取等运算实现访问。
- 非关系型数据库:ElastecSearch、MongoDB、Redis,多数使用哈希表,表中以键值(key-value)的方式实现特定的键和一个指针指向的特定数据。
三、数据库管理系统
3.1 概念
数据库管理系统(DataBase Management System,DBMS):指一种操作和管理数据库的大型软件,用于建立、使用、和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性。用户通过数据库管理系统访问数据库中的数据。
3.2 常见数据库管理系统
- Oracle:被认为是业界目前比较成功的关系型数据库管理系统。Oracle数据库可以运行在UNIX、Windows等主流操作平台,完全支持所有的工业标准,并获得最高级别的ISO标准安全性认证。
- DB2:IBM公司的产品,DB2数据库采用多进程多线索体系结构,其功能足以满足大中公司的需求,并可灵活地服务于中小型电子商务解决方案。
- SQL Server: Microsoft公司退出的关系型数据库管理系统。具有使用方便可伸缩性好与相关软件集成程度高等优点。
- SQLLite:应用在手机端的数据库。
四、MySQL
4.1 简介
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,属于Oracle旗下产品。MySQL是最流行的关系型数据库管理系统之一,在WEB应用方面,MySQL是最好RDBM(Relational Database Management System,关系型数据库管理系统)应用软件之一。
4.2 访问与下载
官网地址: https://www.mysql.com/
下载地址: https://dev.mysql.com/downloads/mysql/
mysql安装过程请查看mysql安装指南。
4.3 卸载
- 控制台卸载。
- 找到mysql的安装目录进行删除。
- programdata删除mysql。
- 如果卸载后,有未删除的MySQL服务,可采用手动删除。
- 以管理员身份打开命令行,输入
sc delete MySQL57
,回车。
如果某个MySQL组件无法删除,可以尝试从注册表搜索信息删除相关文件夹。具体可百度。
4.4 配置环境变量
Windows
- 创建MYSQL_HOME:
C:\Program Files\MySQL\MySQL Server5.7
- 追加PATH:
%MYSQL_HOME%\bin;
4.5 MySQL目录结构
核心文件介绍:
文件夹名称 | 内容 |
---|---|
bin | 命令文件 |
lib | 库文件 |
include | 头文件 |
Share | 字符集、语言等信息 |
4.6 MySQL配置文件
在MySQL安装目录中找到my.ini文件,并打开my.ini文件查看几个常用配置参数。
参数 | 描述 |
---|---|
default-character-set | 客户端默认字符集 |
character-set-server | 服务器端默认字符集 |
port | 客户端和服务器端的端口号 |
default-storage-engine | MySQL默认存储引擎INNODB |
通过安装程序安装的MySQL配置文件在C盘的隐藏文件ProgramData中,点进去找到对应的MYSQL目录就能看到my.ini文件了。
客户端默认字符集和服务器端默认字符集必须保持一致,它们在初始的配置文件中都是被注释掉的,那么默认的字符集会跟随你的系统默认字符集。
五、SQL语言
5.1概念
SQL (Structured Query Language)结构化查询语言,用于存取数据、更新、查询和管理关系数据库系统的程序设计语言。
- 经验:通常执行对数据库的“增删改查”,简称c (create) R (Read) u (Update) D (Delete)。
5.2 MySql应用
对于数据库的操作,需要在进入MySQL环境下进行指令输入,并在一句指令的末尾使用;结束
5.3基本命令
查看MvSqL中所有数据库
mysqls SHOW DATABASES;#显示当前MySQL中包含的所有数据库
数据库名称 | 作用 |
---|---|
information_schema | 信息数据库 |
mysql | 核心数据库 |
performance_schema | 性能优化 |
sakila | 样板数据库 |
sys | 系统数据库 |
world | 国家的编号等 |
创建自定义数据库
1 | create database mydb1; # 创建数据库 |
查看数据库创建信息
1 | show create database mydb2; # 查看数据库创建信息 |
修改数据库
1 | alter database mydb2 character set utf8; |
删除数据库
1 | drop database mydb1; # 删除数据库 |
查看当前使用的数据库
1 | select database(); |
使用数据库
1 | use mydb2; |
六、客户端工具
6.1 Navicate
Navicat是一套快速、可靠并价格相宜的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设。它的设计符合数据库管理员、开发人员及中小企业的需要。Navicat 是以直觉化的图形用户界面而建的,让你可以以安全并且简单的方式创建、组织、访问并共用信息。
6.2 SQLyog
MySQL可能是世界上最流行的开源数据库引擎,但是使用基于文本的工具和配置文件可能很难进行管理。SQLyog提供了完整的图形界面,即使初学者也可以轻松使用MySQL的强大功能。其拥有广泛的预定义工具和查询、友好的视觉界面、类似Excel的查询结果编辑界面等优点。
七、数据查询【重点】
7.1 数据库表的基本结构
关系数据库是以表格(Table)进行数据存储,表格由“行”和“列”组成
- 经验:执行查询语句返回的结果是一张虚拟表
7.2 基本查询
语法:SELECT列名FROM表名
关键字 | 描述 |
---|---|
SELECT | 指定要查询的列 |
FROM | 指定要查询的表 |
7.2.1 查询部分列
1 | # 查询员工表中所有员工的编号】你名字、邮箱 |
7.2.2查询所有列
1 | # 查询所有列 |
- 注意:生产环境下,优先使用列名查询,*的方式需要转换成全列名。效率低,可读性差
7.2.3 对列中的数据进行运算
1 | # 查询员工的编号、名字、年薪 |
算数运算符 | 描述 |
---|---|
+ | 两列做加法运算 |
- | 两列做减法运算 |
* | 两列做乘法运算 |
/ | 两列做除法运算 |
- % 是占位符。而并非模运算符
7.2.4 列的别名
列 as 列名
1 | SELECT EMPLOYEE_ID '编号',FIRST_NAME AS '姓氏',SALARY * 12 AS '年薪' FROM t_employees; |
7.2.5 查询结果去重
distinct 列名
1 | # 查询员工表中有多少个经理 |
7.3 排序查询
语法:SELECT 列名 FROM 表名
ORDER BY排序列[排序规则]
排序规则 | 描述 |
---|---|
ASC | 对前面排序列做升序排列 |
desc | 对前面排序列做降序排序 |
7.3.1 依据单列排序
1 | # 对员工工资进行升序排序 |
7.3.2 依据多列排序
1 | # 按照工资高低进行降序排序,如果工资相等,按照员工编号升序进行排序 |
7.4 条件查询
语法: SELECT 列名 FROM 表名 WHERE 条件
关键字 | 描述 |
---|---|
where 条件 | 在查询结果中,筛选符合查询条件的查询结果,条件为布尔表达式 |
7.4.1 等值判断
1 | # 查询符合条件的数据 |
- 注意:与java不同(==),mysql中等值判断使用=
7.4.2 逻辑判断(and 、or、 not)
1 | SELECT EMPLOYEE_ID, FIRST_NAME,salary |
7.4.3 不等值判断(>、 <、>=、<=、<>、!=)
1 | SELECT EMPLOYEE_ID, FIRST_NAME,salary |
7.4.4 区间判断(between 起始and 终止)
1 | # 查询工资区间在[6000, 10000]之间 |
- 注意:在区间判断中,小值在前,大值在后,反之,得不到结果
7.4.5 null值判断(is null、is not null)
1 | # 查询出经理编号为null的员工信息 |
7.4.6 枚举查询(IN(值1, 值2,值3))
1 | # 查询部门编号为70,80,90 的员工信息 |
7.4.7 模糊查询
- LIKE_(单个任由字符)
列名 LIKE ‘张__’
LIKE %(任意长度的任意字符)
列名 LIKE ‘张%’
- 注意:模糊查询只能和LIKE关键字结合使用
1 | # 查询L开头的三个字的员工信息 |
7.4.8 分支结构查询
1 | CASE |
- 注意:通过使用case end进行条件判断,每条数据对应生成一个值
- 经验:类似java中的switch
1 | # 查询员工信息 |
7.5 时间查询
select 时间函数([参数列表])
- 经验:执行时间函数查询,会自动生成一张虚表
时间函数 | 描述 |
---|---|
SYSDATE | 当前系统时间(日月年时分秒) |
CURDATE | 获取当前日期 |
CURTIME | 获取当前时间 |
WEEK(DATE) | 获取指定日期为一年中的第几周 |
YEAR(DATE) | 获取指定日期的年份 |
HOUR(TIME) | 获取指定时间的小时值 |
MINUTE(TIME) | 获取时间的分钟值 |
DATEDIFF(DATE,DATE2) | 获取DATE1和DATE2之间相隔的天数 |
ADDDATE(DATE,N) | 计算DATE加上N天后的日期 |
1 | # 当前系统的时间 |
7.6 字符串查询
语法: SELECT 字符串函数([参数列表])
字符串函数 | 说明 |
---|---|
concat(str1, …) | 将多个字符串拼接 |
insert(str, pos, len, newStr) | 将str中指定pos位置开始len长度的内容替换为newStr |
lower(str) | 将指定字符串转换诶小写 |
upper(str) | 将指定字符串转换为大写 |
substring(str, num, len) | 将str字符串指定num位置开始截取len个内容 |
1 | # 多个字符串拼接 |
7.7 聚合函数
语法: SELECT 聚合函数(列名) FROM 表名;
- 经验:对多条数据的单列进行统计,返回统计后的一行结果
聚合函数 | 说明 |
---|---|
SUM() | 求所有行中单列结果的总和 |
AVG() | 平均值 |
MAX() | 最大值 |
MIN() | 最小值 |
COUNT() | 求总行数 |
1 | # 聚合函数 |
- 注意:聚合函数会自动忽略null值,不进行统计
7.8 分组查询
语法:
SELECT 列名 FROM 表名 WHERE 条件 GROUP BY 分组依据(列);
关键字 | 说明 |
---|---|
GROUP BY | 分组依据,必须在WHERE之后生效 |
1 | # 查询各个部门的额总人数 |
- 分组查询中,select显示的列只能是分组依据列,或者聚合函数列,不能出现其他列
7.9 分组过滤查询
语法:
SELECT 列名 FROM 表名 WHERE 条件 GROUNP BY 分组列 HAVING 过滤规则
关键字 | 说明 |
---|---|
HAVING过滤规则 | 过滤规则定义对分组后的数据进行过滤 |
统计部门的最高工资
1 | #思路 |
7.10 限定查询
语法:
SELECT 列名 FROM 表名 LIMIT 起始行,查询行数
关键字 | 说明 |
---|---|
LIMIT offset_start,row_count | 限定查询结果的起始行和总行数 |
7.10.1 查询前5行记录
1 | #查询表中前五名员工的所有信息 |
- 注意:起始行是从0开始,代表了第一行,第二个参数代表的是从指定行开始查询几行。
7.10.2 查询范围记录
1 | #查询表中从第四行开始,查询10行 |
7.10.3 LIMIT典型应用
分页查询:一页显示10条,一共查询三页。
1 | #思路:第一页是从0开始,显示10条 |
- 在分页应用场景中,起始行是变化的,但是一页显示的页数是不变的
7.11 查询总结
7.11.1 SQL语句编写顺序
COPYSELECT 列名 FROM 表名 WHERE 条件 GROUP BY 分组 HAVING 过滤条件 ORDER BY 排序列(ASC|DESC) LIMIT 起始行,查询行数
7.11.2 SQL语句执行顺序
1 | COPY1.FROM:指定数据来源表 |
7.12 子查询(作为条件判断)
语法:
SELECT 列名 FROM 表名 WHERE 条件(子查询结果)
7.12.1 查询工资大于Bruce的员工信息
1 | #1.先查询到Bruce的工资(一行一列) |
- 注意:将子查询“一行一列”的结果作为外部查询的条件,做第二次查询。
- 子查询得到一行一列的结果才能作为外部查询的等值判断条件或不等值判断条件
7.13 子查询(作为枚举查询的条件)
语法:
SELECT 列名 FROM 表名 WHERE 列名 IN (子查询结果);
7.13.1 查询与名为“KING”同一部门的员工信息
1 | #思路 |
- 将子查询“多行一列”的结果作为外部查询的枚举查询条件,做第二次查询。
7.13.2 工资高于60编号部门的员工信息
1 | #1.查询60编号部门所有人的工资(多行单列) |
注意:当子查询结果集形式为多行单列时可以使用ANY或ALL关键字。
ALL表示查询高于部门所有员工工资的员工信息;ANY表示查询只需要高于部门中任意一名员工工资的员工信息
7.14 子查询(作为一张表)
查询到一张多行多列的临时表,这张表也可以作为查询数据源。
语法:
SELECT 列名 FROM (子查询的结果集) WHERE 条件;
7.14.1 查询员工表中工资排名前5名的员工信息
1 | #思路: |
- 将子查询“多行多列“的结果作为外部查询的一张表,做第二次查询。
- 注意:子查询作为临时表,需要为其赋予一个临时表名。
7.15 合并查询
SELECT * FROM 表名1 UNION SELECT * FROM 表名2
SELECT * FROM 表名1 UNION ALL SELECT * FROM 表名2
- 返回的查询结果是将表1的结果和表2的结果做了一个合并。
15.1 合并两张表的结果(去除重复记录)
1 | #合并两张表的结果,去除重复记录 |
- 注意:合并结果的两张表,列数必须相同,列的数据类型可以不同。
列数必须相同是因为该合并做了一个纵向合并,两个4列多行的结果集表合并后也是一个4列多行的表,但是合并后的列名以第一个结果集表为准。
7.15.2 合并两张表的结果(保留重复记录)
1 | #合并两张表的结果,不去除重复记录(显示所有) |
该合并结果会保留两张查询表中重复的记录,而UNION只保留第一个不重复的记录
7.16 表连接查询
语法:
SELECT 列名 FROM 表1 连接方式 表2 ON 连接条件
7.16.1 内连接查询(INNER JOIN ON)
1 | #1.查询所有员工的职员和职位信息 SQL标准 |
如果没有指定连接条件,则会造成笛卡尔积的结果,第一张表中的每行数据都会和第二张表进行连接。
- 经验:在MySQL中,第二种方式也可以作为内连接查询,但是不符合SQL标准。
- 而第一种属于SQL标准,与其他关系型数据库通用。
7.16.2 三表连接查询
1 | #查询所有员工工号、名字、部门名称、部门所在国家ID |
该语句查询出来的结果没有员工编号为178的员工信息,该名员工的部门ID为NULL,不符合连接条件,所以不包含在匹配出的结果集中,你可以自己动手尝试并查看结果。之所以提这个是因为可以与下节的语句区分开来。
7.16.3 左外连接(LEFT JOIN ON)
1 | #查询所有员工的工号、名字、工资及其对应的部门名称(没有部门的员工也在查询结果中,部门名称以NULL值补充) |
该语句查询出来的结果包含没有部门的178号员工,DEPARTMENT_NAME的值被填充为NULL。
- 注意:左外连接,是以左表作为主表,依次向右匹配,匹配到则返回结果;
- 匹配不到则返回NULL值填充。
7.16.4 右外连接(RIGHT JOIN ON)
1 | #查询所有部门信息,以及此部门中的所有员工信息(没有员工的部门也在查询结果中,员工信息以NULL值填充) |
该查询结果以部门表作为主表,有些部门没有员工,其员工信息全部为NULL。
- 注意:右外连接,是以右表为主表,依次向左匹配,匹配到返回结果。
- 匹配不到,则返回NULL值填充。
八、DML操作【重点】
DDL(Data Manipulation Language)数据库操纵语言,是其中一类SQL语言,其实也就是增删改。
8.1 新增(INSERT)
语法:
INSERT INTO 表名(列1,列2,列3......) VALUES(值1,值2,值3......);
8.1.1 添加一条信息
1 | #添加一条岗位信息 |
- 注意:表名后的列名要和VALUE里的值一一对应(个数、顺序、类型)。
8.2 修改(UPDATA)
1 | #修改编号为100的员工工资为25000 |
- 注意:SET后多个列名=值,绝大多数情况下都要加WHERE条件指定修改,否则为整表更新。
8.3 删除(DELETE)
语法:DELETE FROM 表名 WHERE 条件;
1 | #删除编号为135的员工 |
- 注意:删除时,如果不加条件,则默认删除整张表。
用DELETE删除整表是不彻底的,它只是删除了内容,并没有改变表的结构。
8.4 清空整表数据(TRUNCATE)
1 | COPYTRUNCATE TABLE 表名; |
8.4.1 清空整张表
1 | COPY#清空t1整张表 |
- 注意:与DELETE不加WHERE删除整表数据不同,TRUNCATE是把原表销毁,再按原表的格式创建一张新表。
九、数据表操作
9.1 数据类型
MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。对于我们约束数据的类型有很大的帮助。
9.1.1 数值类型
类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
---|---|---|---|---|
INT | 4字节 | (-2147483648,2147483647) | (0,4294967295) | 大整数值 |
DOUBLE | 8字节 | (-1.797E+308,-2.22E-308) | 0,(2.22E-308,1.797E+308) | 双精度浮点数值 |
DOUBLE(M,D) |
8字节,M表示长度,D表示小数位数 | 同上,受M和D的约束;如DOUBLE(5,2) -999.99~999.99 | 同上,受M和D的约束 | 双精度浮点数值 |
DECIMAL(M,D) | DECIMAL(M,D) | 依赖于M和D的值,M最大值为65 | 依赖于M和D的值,M最大值为65 | 小数值 |
9.1.2 日期类型
类型 | 大小 | 范围 | 格式 | 用途 |
---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | ‘-838:59:59’/‘838:59:59’ | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 |
DETETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 |
9.1.3 字符串类型
类型 | 大小 | 用途 |
---|---|---|
CHAR | 0-255 bytes | 定长字符串 |
VARCHAR | 0-65535 bytes | 变长字符串 |
BLOB(binary large object) | 0-65 535 bytes | 二进制形式的长文本数据 |
TEXT | 0-65 535 bytes | 长文本数据 |
- CHAR和VARCHAR类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同,CHAR(N)会将多余的存储位以空格补足,而VARCHAR(N)则会根据实际存储长度进行“压缩”。在存储或检索过程中不进行大小写转换。
- BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。
9.2 数据表的创建(CREATE)
1 | CREATE TABLE 表名( |
括号内的内容为可选。
9.2.1 创建表
列名 | 数据类型 | 说明 |
---|---|---|
subject_id | INT | 课程编号 |
subject_name | VARCHAR(20) | 课程时间 |
subject_hours | INT | 课程课长 |
1 | #根据上述表格创建数据库,并向表中插入3条测试语句 |
9.3 数据表的修改(ALTER)
语法:
ALTER TABLE 表名 操作;
9.3.1 向现有表中添加列
1 | #在课程表基础上添加grade_id列 |
9.3.2 修改表中的列
1 | #修改课程表中的课程名称长度为10个字符 |
- 注意:修改表中的某列时,也要写全列的名字,数据类型,约束。
9.3.3 删除表中的列
1 | #删除课程表中grade_id列 |
- 注意:删除列时,每次只能删一列。
9.3.4 修改列名
1 | #修改课程表中subject_hours列为class_hours |
- 注意:修改列名时,在给定列新名称时,要指定列的类型和约束。
9.3.5 修改表名
1 | #修改课程表的t_subject为t_sub |
9.4 数据表的删除(DROP)
语法:
DROP TABLE 表名
9.4.1 删除课程表
1 | #删除课程表 |
十、约束
问题:在往已创建表中新增数据时,可不可以新增两行相同列的数据?如果可行,会有什么弊端?
这是可以的,但重复的数据不仅会浪费空间,而且对查询结果不利,也是多余的。在实际的存储中应尽量保证每条数据的唯一性。
10.1 实体完整性约束
表中的一行数据代表一个实体(entity),实体完整性的作用即是标识每一行数据不重复,实体唯一。
10.1.1 主键约束
关键词:
PRIMARY KEY
唯一,标识表中的一行数据,此列的值不可重复,且不能为NULL。
1 | #为表中适用主键的列添加主键约束 |
作为主键的字段一般都是也应该是编号、学号、工号等字段。
10.1.2 唯一约束
关键字:
UNIQUE
唯一,标识表中的一行数据,不可重复,可以为NULL。
1 | #为表中列值不允许重复的列添加唯一约束 |
10.1.3 自动增长列
关键字:
AUTO_INCREAMENT
自动增长,给主键数值列添加自动增长。从1开始,每次加1。不能单独使用,和主键配合。
1 | #为表中主键列添加自动增长,避免忘记主键ID序号 |
10.2 域完整性约束
该约束限制单元格的数据正确性。
10.2.1 非空约束
语法:
NOT NULL
,非空,此列必须有值
1 | #课程名称虽然添加了唯一约束,但是有NULL值存在的可能,要避免课程名称为NULL。 |
10.2.2 默认值约束
关键字:
DEFAULT 值
。为列赋予默认值,当新增数据不指定值时,书写DEFAULT,以指定的默认值进行填充。
1 | #当存储课程信息时,若课程时长没有指定值,则以默认值进行填充 |
10.2.3 引用完整性约束
语法:
CONSTRAINT 引用名 FOREIGN KEY (列名) REFERENCES 被引用表名(列名)
解释:FOREIGN KEY引用外部表某个列的值,新增数据时,约束此列的值必须是引用表中存在的值。
1 | #创建专业表 |
- 注意:当两张表存在引用关系时,要执行删除操作,一定要先删除从表(引用表),再删除主表(被引用表)。
10.3 约束创建整合
创建带有约束的表。
列名 | 数据类型 | 约束 | 说明 |
---|---|---|---|
grade_id | INT | 主键、自动增长 | 班级编号 |
grade_name | VARCHAR(20) | 唯一、非空 | 班级名称 |
1 | CREATE TABLE t_grade( |
列名 | 数据类型 | 约束 | 说明 |
---|---|---|---|
student_id | VARCHAR(20) | 主键 | 学号 |
student_name | VARCHAR(20) | 非空 | 姓名 |
sex | CHAR(2) | 默认填充“男” | 性别 |
born_date | DATE | 非空 | 生日 |
phone | VARCHAR(11) | 无 | 电脑 |
grade_id | INT | 非空、外键约束引用班级表的grade_id | 班级编号 |
1 | CREATE TABLE t_student( |
- 注意:创建关系表时,一定要先创建主键,再创建从表。
- 删除关系表时,先删除从表,再删除主表。
十一、事务【重点】
11.1 模拟转账
生活当中转账是转账方账户扣钱,收账方账户加钱。我们用数据库操作来模拟实现转账。
11.1.1 数据库模拟转账
1 | #A账户转账给B账户1000元 |
- 上述代码完成了两个账户之间转账的操作。
11.1.2 模拟转账错误
1 | UPDATE t_account SET money=money-1000 WHERE account_id=1;#转账 |
- 上述代码在减操作后过程中出现了异常或加钱语句出错,会发现减钱成功了而加钱失败了!
- 注意:每条SQL语句都是一个独立的操作,一个操作执行完对数据库是永久性的影响。
11.2 事务的概念
事务是一个原子操作,是一个做小执行单元。可以由一个或多个SQL语句组成,在同一个事务当中,所有的SQL语句都成功执行,整个事务成功,有一个SQL语句执行失败,整个事务执行失败。
11.3 事务的边界
- 开始:连接到数据库,执行一条DML语句。上一个事务结束后,又输入了一条DML语句,即事务的开始。
- 结束:
- 提交:
- 显式提交:COMMIT;
- 隐式提交:一条创建、删除的语句,正常退出(客户端退出连接);
- 回滚:
- 显式回滚:ROLLBACK;
- 隐式回滚:非正常退出(断电、宕机),执行了创建、删除的语句,但是失败了,会为这个无效的语句执行回滚。
- 提交:
如11.1.2节中的两条语句就是两个事务,第一条语句执行便是事务的开始,分号便是事务的结束,执行完毕该语句就被提交了;而第二句由于执行失败,该语句的结果就是回滚,回到事务前的样子。
11.4 事务的原理
数据库会为每一个客户端都维护一个空间独立的缓存区(回滚段),一个事务中所有的增删改查语句的执行结果都会缓存在回滚段中,只有当事务中所有SQL语句均正常结束(COMMIT),才会将回滚段中的数据同步到数据库。否则无论因为哪种原因失败,整个事务将回滚(ROLLBACK)。
11.5 事务的特性(ACID)
Atomicity(原子性)
表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败。
Consistency(一致性)
表示一个事务内有一个操作失败时,所有更改过的数据都必须回滚到修改前状态。
Isolation(隔离性)
事务查看数据库操作时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事物修改它之后的状态,事务不会查看中间状态的数据。
Durability(持久性)
持久性事务完成之后,它对与系统的影响是永久性的。
11.6 事务应用
应用环境:基于增删改查语句的操作结果(均返回操作后受影响的行数),可通过程序逻辑手动控制事务提交或回滚。
11.6.1 事务完成转账
手动开启事务,将两个减钱和加钱的操作放到事务中,操作完之后再提交。
1 | #开启事务 |
以上SQL语句开启了事务,但并未进行提交,此时查看账户中的数据如下:
account_id | money |
---|---|
1 | 4000 |
2 | 6000 |
发现数据已经变了,但该数据只是事务的中间状态。
然后在你的数据库管理系统中新建一个连接,新建连接名随便取一个,然后新建查询。这么做相当于模拟了另外一个客户端:
执行SELECT * FROM t_account
;,发现表中的数据并没有改变:
account_id | money |
---|---|
1 | 5000 |
2 | 5000 |
这是因为在第一个连接中开启了事务,但没有提交;而在another连接中,查询语句也是一个事务(没有显式开启和显式提交),该事务只能查看其它事务修改前后者修改后的状态,此处就是只能查看转账操作提交前的状态,两个账户都是5000,这也是事务的隔离性。
回到localhost连接中,提交事务;然后在another连接中再查询一次:
1 | #localhost连接,提交事务 |
此时的查询结果如下:
account_id | money |
---|---|
1 | 4000 |
2 | 6000 |
发现数据已经正式修改完毕。
回滚操作类似,但它是取消掉事务的操作,回到事务前的状态。比如事务开启后,减钱成功,但是加钱失败了(可以用SQL语句某个单词写错来模拟),然后手动执行ROLLBACK
,减钱操作就会被撤销。不再演示。
- 此处的演示是手动进行了事物的开启和提交/回滚,在写程序时,这些操作都会在程序中进行控制。
十二、权限管理
12.1 创建用户
语法:
CREATE USER 用户名 IDENTIFIED BY 密码
1 | #创建一个用户 |
接下来验证用户是否添加成功,首先新建连接,在用户名和账号那里写上自己创建的用户和密码,测试一下是否连接成功。
然后点“确定”。但是打开该连接之后你会发现此连接中除了一个系统数据库,其他数据库都不存在。这是因为client1用户建立的连接没有得到任何授权,也就是没有对数据库的访问操作权限。
12.2 授权
语法:
GRANT ALL ON 数据库.表 TO 用户名;
1 | #将companydb下的所有表的权限都赋给client |
该语句需要在root连接中执行,不能在client1连接中自己给自己授权。
12.3 撤销权限
语法:
REVOKE ALL ON 数据库.表名 FROM 用户名
- 注意:撤销权限后,账户需要重新连接客户端才会生效。
1 | #将client1的companydb的操作权限撤销 |
虽然刷新之后表不见了,但是依然可以对表进行操作,只有在重新连接数据库的时候权限才会消失。
12.4 删除用户
语法:
DROP USER 用户名
1 | #删除用户client1 |
十三、视图
13.1 概念
视图,虚拟表,从一个表或多个表中查询出来的表,作用和真实表一样,包含一系列带有行和列的数据。视图表中,用户可以使用SELECT语句查询数据,也可以使用INSERT、UPDATE、DELETE修改记录,视图可以使用户操作方便,并保障数据库系统安全。
- 和临时表很像,但临时表不会被保存,而视图是保存下来的表。
13.2 视图特点
- 优点
- 简单化,数据所见即所得。
- 安全性,用户只能查询或修改他们所能见到的数据。
- 逻辑独立性,可以屏蔽真实表结构变化带来的影响。
- 缺点
- 性能相对较差,简单的查询也会变得稍显复杂。
- 修改不方便,特别是复杂的聚合视图基本无法修改。
13.3 视图的创建
语法:
CREATE VIEW 视图名 AS 查询数据源表结构语句;
13.3.1 创建视图
1 | #创建t_emp_info的视图,其视图从t_employees表中查询员工编号、姓名、邮箱、工资 |
13.3.2 使用视图
1 | #查询t_emp_info视图中编号为036的员工信息 |
使用视图可以简化查询的操作,将来视图应用最多的地方也是查询。
13.4 视图的修改
- 方式一:
CREATE OR REPLACE VIEW 视图名 AS 查询语句
- 方式二:
ALTER VIEW 视图名 AS 查询语句
方式一是在不明确视图是否存在时使用,如果存在则修改,否则创建;方式二是明确存在时进行修改。无论哪种方式都需要拼接一个完整查询语句。
1 | #方式一,如果视图存在则修改,反之创建。 |
13.5 视图的删除
语法:
DROP VIEW 视图名
1 | #删除视图 |
- 注意:删除视图不会影响原表。
13.6 视图的注意事项
- 视图不会独立存储数据,原表发生改变,视图也发生改变。没有优化任何查询性能。
- 如果视图包含以下结构中的一种,则视图不可更新:
- 聚合函数的结果
- DISTINCT去重后的结果
- GROUP BY分组后的结果
- HAVING筛选过滤后的结果
- UNION、UNION ALL联合后的结果
十四、SQL语言分类
- 数据查询语言DQL(Data Query Language):SELECT、WHERE、ORDER BY、GROUP BY、HAVING;
- 数据定义语言DDL(Data Definition Language):CREATE、ALTER、DROP;
- 数据操作语言DML(Data Manipulation Language):INSERT、UNPATE、DELETE;
- 事务处理语言TPL(Transaction Process Language):COMMIT、ROLLBACK;
- 数据控制语言DCL(Data Control Language):GRANT、REVOKE。
十五、综合练习
某网上购物商城数据库表的结构如下:
1 | # 创建用户表 |
15.1 综合练习1-【多表查询】
查询所有用户的订单
1
2
3# 查询所有用户的订单
# 用户 订单表
SELECT * FROM USER INNER JOIN orders ON orders.`userId` = user.`userId`;
查询用户id为1的所有订单详情
1
2
3
4
5
6
7
8# 查询用户id为1的所有订单详情
# 用户 订单 订单详情表
SELECT * FROM USER
INNER JOIN orders
ON orders.`userId` = user.`userId`
INNER JOIN orderitem
ON orders.`oid` = orderitem.`oid`
WHERE user.`userId` = 1;
15.2 综合练习2-【子查询】
查看用户为张三的订单
1
2
3
4# 查看用户为张三的订单
# 子查询单行单列
SELECT userId FROM USER WHERE username='张三';
SELECT * FROM orders WHERE userId=(SELECT userId FROM USER WHERE username='张三');
查询出订单的价格大于800的所有用户的信息
1
2
3
4# 查询出订单的价格大于800的所有用户的信息
# 子查询 多行单列 枚举查询
SELECT DISTINCT userId FROM orders WHERE totalprice > 800;
SELECT * FROM USER WHERE userId IN (SELECT DISTINCT userId FROM orders WHERE totalprice > 800);
15.3 综合练习3-【分页查询】
查询所有订单信息,每页显示5条数据
1
2
3
4
5# 查询所有订单信息,每页显示5条数据
# 查询第一页
SELECT * FROM orders LIMIT 0, 5;
# 查询第二页
SELECT * FROM orders LIMIT 5, 5;