写在前面:
1.本文是笔者自学MySQL基础之后进行的一次梳理总结,总体来说重语法,轻原理,而且也非常基础,所以本文比较适合快速入门的学习以及学习数据库前期作为查询语法的工具。
2.文中若有不当或有误之处,欢迎各位大佬评论区指正❤️❤️❤️
MySQL基础总结
一、SQL通用语法
-
SQL
语句可以单行或多行书写,以分号结尾 -
MySQL
数据库的SQL
语句不区分大小写 -
注释:
单行注释:"
-- 注释内容
“或”#注释内容
"(该方式为MySQL特有)-- 注释内容 #注释内容
注意:
- "
--
"后面必须加空格才能有注释效果 - 第二种为MySQL特有
多行注释:"
/*注释内容*/
"/* 注释内容 */
- "
二、数据库定义语法
1、对数据库的操作
-
查询数据库(展示所有数据库)
-- 查询数据库 SHOW DATABASES;
-
创建数据库
-- 创建数据库sqltest CREATE DATABASE sqltest; -- 先判断数据库sqltest是否存在,不存在则创建 CREATE DATABASE IF NOT EXISTS sqltest;
创建数据库的语法:
"CREATE DATABASE 数据库名称" 或 "CREATE DATABASE IF NOT EXISTS 数据库名称"
-
删除数据库
-- 删除数据库sqltest DROP DATABASE sqltest; -- 先判断数据库sqltest是否存在,存在则删除 DROP DATABASE IF EXISTS sqltest;
删除数据库的语法:
"DROP DATABASE 数据库名称" 或 "DROP DATABASE IF EXISTS 数据库名称"
-
使用数据库
-- 使用数据库 USE sqltest; -- 查看当前使用的数据库 SELECT DATABASE();
使用数据库的语法:
USE 数据库名称
查看当前使用的数据库语法:
SELECT DATABASE()
2、对表的操作
-
查询表
查询当前数据库下所有表的名称
-- 查询当前数据库下所有表的名称 SHOW TABLES;
查询当前数据库下所有表的名称语法:
SHOW TABLES
查询表结构
-- 查询stu表结构 DESC stu;
查询表结构语法:
DESC 表名
-
创建表
-- 创建表 CREATE TABLE user( user_name CHAR(32), password CHAR(16), name CHAR(16), job CHAR(16) );
创建表语法:
CREATE TABLE 表名(
字段1 数据类型1,
字段2 数据类型2,
字段3 数据类型3,
···
字段n 数据类型n
)关于
MySQL
的常用数据类型因是基础总结,此处仅对常用的数据类型进行了罗列
数据类型 说明 TINYINT
1字节整数值(0~28-1的整数数) SMALLINT
2字节整数值(-215~215-1的整数) INT
4字节整数值(-231~231-1的整数) CHAR
1~255个字符的定长字符串 VARCHAR
可变长文本 FLOAT
浮点值 BIT
单个二进制位值,或者为0或者为1,主要用于开关标志 DATE
日期值(YYYY-MM-DD) DATETIME
日期时间值(YYYY-MM-DD HH:MM:SS) -
删除表
-- 删除表 DROP TABLE user; -- 先判断表user是否存在,存在则删除 DROP TABLE IF EXISTS user;
删除表语法:
"DROP TABLE 表名称" 或 "DROP TABLE IF EXISTS 表名称"
-
修改表
修改表名
-- 修改表名 ALTER TABLE user RENAME TO s_user;
修改表名语法:
ALTER TABLE 表名 RENAME TO 新表名
添加一列
ALTER TABLE user ADD s_power TINYINT;
添加一列语法:
ALTER TABLE 表名 ADD 列名 数据类型
修改数据类型
-- 修改数据类型 ALTER TABLE user MODIFY s_power INT;
修改数据类型语法:
ALTER TABLE 表名 MODIFY 列名 新数据类型
修改列名和数据类型
-- 修改列名和数据类型 ALTER TABLE user CHANGE s_power spw TINYINT;
修改列名和数据类型语法:
ALTER TABLE 表名 CHANGE 列名 新列名 新数据类型
删除列
-- 删除列 ALTER TABLE user DROP spw;
删除列语法:
ALTER TABLE 表名 DROP 列名
三、数据库操作语法
-
添加数据
给指定列添加数据
-- 给指定列添加数据 INSERT INTO user(user_name,password,name,job) VALUES("lisi1234","lisi","李四","学生");
给指定列添加数据语法:
INSERT INTO 表名(列名1,列名2,列名3,···)
VALUES(值1,值2,值3,···);给全部列添加数据
-- 给全部列添加数据 INSERT INTO user VALUES("wangwu666","wangwu","王五","学生");
给全部列添加数据语法:
INSERT INTO 表名 VALUES(值1,值2,值3,···)
批量添加数据
-- 指定列批量添加数据 INSERT INTO user(user_name,password,name,job) VALUES ("hwd6666","hwd1001","黄武迪","教导主任"), ("ttz6666","ttz1001","唐泰踪","教导主任"); -- 全部列批量添加数据 INSERT INTO user VALUES ("xs0802","xishi","西施","学生"), ("wzj0528","wzj1001","王昭君","学生");
指定列批量添加语法:
INSERT INTO 表名(列名1,列名2,列名3,···) VALUES
(值1,值2,值3,···),
(值1,值2,值3,···)
全部列批量添加语法:
INSERT INTO 表名 VALUES
(值1,值2,值3,···),
(值1,值2,值3,···)
-
修改数据
-- 修改数据 UPDATE user SET password="qsh6666" WHERE user_name="qsh6666";
修改数据语法:
UPDATE 表名 SET 列名1=值1,列名2=值2,··· WHERE 条件
-
删除数据
-- 删除数据 DELETE FROM user WHERE user_name="wzj0529";
删除数据语法:
DELETE FROM 表名 WHERE 条件
四、数据库查询语法
1、基础查询
-
查询指定列
-- 查询指定列 SELECT user_name,password FROM user;
查询指定列语法:
SELECT 列名1,列名2,··· FROM 表名
-
查询所有列
-- 查询所有列 SELECT * FROM user;
查询所有列语法
SELECT * FROM 表名
-
拓展语法
去除重复记录
SELECT DISTINCT user_name,password FROM user;
语法:
SELECT * FROM 表名
起别名
SELECT user_name AS uname,password AS pword FROM user;
语法:
SELECT * FROM 表名
2、条件查询
初始表数据:
id | name | age | sex | address | math | english | hir_date |
---|---|---|---|---|---|---|---|
1 | 马堡国 | 56 | 男 | 杭州 | 67 | 98 | 1998-05-29 |
2 | 王晓芳 | 42 | 女 | 深圳 | 99 | 87 | 1994-09-13 |
3 | 刘强北 | 50 | 男 | 香港 | 89 | 100 | 1997-03-05 |
4 | 刘辉 | 27 | 女 | 长沙 | 85 | 91 | 2021-01-09 |
5 | 王子枫 | 22 | 男 | 长沙 | 88 | 82 | 2020-11-12 |
6 | 张丽丽 | 32 | 女 | 香港 | 77 | 75 | 2003-04-26 |
7 | 周殿梁 | 56 | 男 | 香港 | 75 | 79 | 2001-07-21 |
8 | 宇文青峰 | 19 | 男 | 南京 | 56 | 37 | 2021-07-08 |
-
示例
-- 1. 等于条件 -- 条件:姓名为王子枫 SELECT password FROM user WHERE name="王子枫"; -- 2. BETWEEN ··· AND ···条件 -- 条件:数学分数在85和100之间(包括85和100) SELECT name,address,math FROM stu WHERE math BETWEEN 85 AND 100; -- 3. IN 条件 -- 条件:地址为 长沙、香港或杭州 SELECT name,address,math FROM stu WHERE address IN("长沙","香港","杭州"); -- 4. 复合查询 -- 条件:数学分数在85和100之间(包括85和100) 并且 地址为 长沙、香港或杭州 SELECT name,address,math FROM stu WHERE math BETWEEN 85 AND 100 AND address IN("长沙","香港","杭州"); -- 5. 模糊查询1(通配符"%"过滤) -- 条件:姓名的第一个字为刘(即姓刘) SELECT * FROM stu WHERE name LIKE "刘%"; -- 6. 模糊查询2(通配符"_"过滤) -- 条件:姓名的第一个字为刘且后面只有一个字(即姓名只有两个字且姓刘) SELECT * FROM stu WHERE name LIKE "刘_";
-
条件查询语法
SELECT 列名1,列名2,··· FROM 表名 WHERE 条件列表
-
条件
条件 解释 >
大于 <
小于 >=
大于等于 <=
小于等于 =
等于 <>
或!=
不等于 BETWEEN
···AND
···在某个范围之内(两头都包含) IN(···)
多选一(条件之间逗号隔开) LIKE
模糊查询 IS NULL
是NULL AND
或&&
并且 OR
或||
或者 NOT
或!
非,不是 -
模糊查询
通配符:
通配符 意义 例(省去LIKE即其之前的语句) %
任何字符出现任意次数 %IK%
可以匹配MIKE
,PUIKILE
等_
任何字符出现一次 _IK_
可以匹配MIKE
,HIKE
等[]
多个字符之一出现一次 [HMT]%
可以匹配HURT
,MIKE
,TRIM
等^
否定,和 []
一同使用^[HMT]%
不可以匹配H M T
开头的字符串使用模糊查询需要注意:
- 不要过度使用通配符。因为通配符搜索一般比其他搜索要更耗费时间
- 确实需要使用通配符时,尽量不要把他们放到搜索模式的开始处。因为种情况下,搜索起来是最慢的
- 使用通配符时,一定要细心检查其位置。因为放错地方会使搜索情况和你的预期相差甚远
3、排序查询
-
示例
-- sorting query SELECT * FROM stu ORDER BY math ASC;#ascending order SELECT * FROM stu ORDER BY english DESC;#descending order
排序查询语法:
SELECT 列名1,列名2,··· FROM 表名 ORDER BY
排序字段名1 排序方式1,
排序字段名2 排序方式2,
···
排序字段名n 排序方式n关于多个排序字段名:
先按字段1排列,字段1相同时再按字段2···,依此类推
关于排序方式
1. ASC: 升序排列(默认值)
2. DESC: 降序排列
4、聚集函数
-
概念:将一列数据作为一个整体,进行纵向计算
-
聚集函数表:
函数 说明 COUNT
统计数量,一般选用不为NULL的列 MAX
最大值 MIN
最小值 SUM
求和 AVG
平均值 -
聚集函数使用语法:
SELECT 聚集函数名(列名) FROM 表名
注:
1.
NULL
值不参与所有聚集函数运算2.
COUNT(*)
统计所有列时,只要有一列不为NULL
就会被统计3.第一条和第二条不矛盾!就是因为有了第一条才会强调一遍第二条
-
使用示例
-- 1.COUNT() 得到的是查询列的值的数量 SELECT COUNT(name) FROM stu;#查询表中的姓名数 SELECT COUNT(*) FROM stu;#查询表中有值的行的数量 -- 2.MAX() 得到的是查询列的最大值 SELECT MAX(math) FROM stu;#查询数学的最高分 -- 3.MIN() 得到的是查询列的最小值 SELECT MIN(english) FROM stu;#查询英语的最低分 -- 4.SUM() 得到的是查询列的值的和 SELECT SUM(math) FROM stu;#查询数学分数的总和 -- 5.AVG() 得到的是查询列的值的平均值 SELECT AVG(age) FROM stu;#查询平均年龄
5、分组查询
-
示例
-- 分组查询 SELECT address,COUNT(address) FROM stu GROUP BY address; /* 查询结果是一列address,一列COUNT(address) 该结果呈现出的逻辑意义就是统计相同address的个数 */
-
分组查询语法
SELECT 字段列表 FROM 表名 GROUP BY 分组字段名
注:
1. 字段列表里可以包含聚集函数
2. SELECT 的字段一般是一个表的属性和一个聚合函数用于统计相关数据
3. 如果查询列表里面包含聚合函数,该聚合函数是对分组后的数据进行操作的 -
过滤分组后数据(
HAVING
)-- 对分组后数据进行过滤 SELECT address,COUNT(address) FROM stu GROUP BY address HAVING COUNT(address)>1; #相当于把对address的统计数据里面的address<=1的过滤掉
关于
WHERE
与HAVING
的区别1. 执行时机不一样。
WHERE
是分组之前进行限定,不满足WHERE
条件则不参与分组,而HAVING
是分组后对数据进行过滤
2. 可判断的条件不一样。WHERE
不能对聚合函数进行过滤,而HAVING
可以
6、分页查询
1.分页查询可以被理解为对查询结果的一种限制,是对检索数据的起始行和检索出来的行数的一种限制
2.需要注意的是,该种查询方言性较强,即在不同的数据库语言中使用的子句大概率是不同的,此处详细介绍MySQL的分页查询方言,其它的个别方言会稍有涉及
-
示例
-- 分页查询 SELECT * FROM stu LIMIT 3,2; #该查询语句的作用是:以第4(4=3+1)作为起始索引,查询不超过两条的数据 #从第4条开始的原因是,第一条的索引是0 #之所以会说不超过两条,是因为表中数据可能不足四条(查出0条数据)或者只有四条(查出1条) SELECT * FROM stu LIMIT 3; #该查询语句的查询结果是从第一条到第3条共三条数据(或者说不到三条,参见上条语句的注释) #该种语句相当于上条语句的第一个数字为0,第二个数字为3
-
分页查询语法
SELECT 字段列表 FROM 表名 LIMIT 起始索引,查询条目数;
-
关于分页查询的方言问题
1.分页查询LIMIT
是MySQL数据库的方言
2.Oracle 分页查询使用的是ROWNUM
3.SQL Server 分页查询使用的是top
7、子查询
-
示例
-- 第一个查询 SELECT name,age FEOM emp WHERE dep_id=1; #查询结果为dep_id为1的员工的姓名和年龄 -- 第二个查询 SELECT id FROM dept WHERE dep_name="研发部"; #查询结果为dep_name为研发部的部门的id -- 使用子查询 SELECT name,age FROM emp WHERE dep_id IN (SELECT id FROM dept WHERE dep_name="研发部"); #查询结果为dep_id为dep_name为研发部的部门id的员工姓名与年龄
-
子查询的逻辑意义
相当于两个表中的的两个不同意义的字段通过两个表中拥有的具有相同意义的字段进行间接沟通
在语法上就是把查询条件换成了另一个查询语句作为子句实现了一种类似嵌套的操作
-
关于起别名的知识补充
-- 起别名 SELECT id,name,math AS m_score,english AS e_score FROM stu; #查询结果的math列的字段会显示为m_score,english则会显示为e_score
起别名方式:
直接在查询字段的后面加上
AS 别名
8、SELECT 子句顺序
-
SELECT
子句表子句 说明 是否必须使用 SELECT
要返回的列或表达式 是 FROM
从中检索数据的表 仅在从表中选择数据时使用 WHERE
行级过滤 否 GROUP BY
分组说明 仅在按组计算聚集时使用 HAVING
组级过滤 否 ORDER
输出排序顺序 否 -
集成使用示例
-- 集成使用查询子句 SELECT address,COUNT(address) FROM stu WHERE math>=60 GROUP BY address HAVING COUNT(address)>1 ORDER BY COUNT(address) DESC;
查询结果的逻辑意义:
数学分数高于60的学生里面(
WHERE
的行级过滤效果),按照字段address
分组后(GROUP BY
的分组说明效果,每组中数据的address
的值都是相同的),分好的组中address
的总数大于1的组(HAVING
的组级过滤效果),返回每组的adress
和COUNT(adress)
的数据(SELECT
的返回数据效果),并根据COUNT(adress)
按降序排序(ORDER BY
的排序效果)
五、SQL特性
1、约束
约束的概念和分类
-
约束的概念
1. 约束是作用于表中列上的规则,用于限制加入表的数据
2. 约束的存在保证了数据库中数据的正确性,有效性和完整性 -
约束的分类
约束类型 说明 语句 非空约束 保证列中所有数据不能有NULL值 NOT NULL
唯一约束 保证列中所有数据各不相同 UNIQUE
主键约束 主键使一行数据的唯一标识,要求非空且唯一 PRIMARY KEY
检查约束 保证列中值满足某一条件 CHECK
外键约束 外键用来让两个表中的数据建立连接,保证数据的一致性和完整性 FOREIGN KEY
注:
MySQL直到8.0.16版本才开始支持检查约束
添加或删除约束的语法
-
添加约束
-- 建表时添加约束 CREATE TABLE courses( c_id SMALLINT PRIMARY KEY, c_name CHAR(16) NOT NULL UNIQUE, c_stu_num SMALLINT ); -- 建完表后添加约束 ALTER TABLE courses MODIFY c_stu_num SMALLINT NOT NULL;
添加约束语法:
1.建表时添加约束
CREATE TABLE 表名(
字段1 数据类型1 约束类型1 约束类型2 ···,
···
)2.建完表后添加约束
ALTER TABLE 表名 MODIFY 列名 数据类型 约束类型1 约束类型2 ···
-
删除约束
-- 删除约束 ALTER TABLE course MODIFY c_stu_num SMALLINT; #和第二种增加约束的方式类似,就是通过修改字段来达到目的
删除约束语法
ALTER TABLE 表名 MODIFY 列名 数据类型
外键约束
-
外键的概念
外键用来让两个表中的数据建立连接,保证数据的一致性和完整性
-
添加外键约束
-- 建表时添加外键 CREATE TABLE s_c_score( s_id SMALLINT NOT NULL, c_id SMALLINT NOT NULL, score TINYINT NOT NULL, CONSTRAINT fk_s_id FOREIGN KEY (s_id) REFERENCES stu (id) ); -- 建完表后添加外键 ALTER TABLE s_c_score ADD CONSTRAINT fk_c_id FOREIGN KEY (c_id) REFERENCES courses (c_id);
添加外键语法:
1.建表时添加外键
CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表 (主表列名)
2.建完表后添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表 (主表列名)
-
删除外键约束
-- 删除外键 ALTER TABLE s_c_score DROP FOREIGN KEY fk_c_id;
删除外键语法
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称
2、多表查询
-
内连接
-- 内连接 SELECT * FROM emp,dept WHERE emp.dep_id=dept.id;#隐式内连接 SELECT * FROM emp INNER JOIN dept ON emp.dep_id=dept.id;#显示内连接
内连接语法:
1.隐式内连接
SELECT 字段列表 FROM 表1,表2 WHERE 条件
2.显示内连接
SELECT 字段列表 FROM 表1 INNER JOIN 表2 条件
内连接的逻辑意义:
查询结果为表1表2满足条件的交集部分
例如这两张表
emp
和dept
:
内连接查询结果为:
因为查询的是两表在emp.dep_id=dept.id
这一条件下的交集,所以不满足条件的所有数据均无法检索得到 -
外连接
-- 外连接(OUTER可省略) SELECT * FROM emp LEFT OUTER JOIN dept ON emp.dep_id=dept.id#左外连接 SELECT * FROM emp RIGHT OUTER JOIN dept ON emp.dep_id=dept.id;#右外连接
外连接语法:
1.左外连接
SELECT 字段列表 FROM 表1 LEFT OUTER JOIN 表2 ON 条件
2.右外连接
SELECT 字段列表 FROM 表1 RIGHT OUTER JOIN 表2 ON 条件
外连接的逻辑意义:
左外连接查询结果为表1不符合条件的部分加上二者条件下的交集部分
右外连接查询结果为表2不符合条件的部分加上二者条件下的交集部分还拿那两张表为例
左外查询结果:
右外查询结果:
如此来看,便清晰多了,左外查询便是内查询加上不满足条件的表1,右外查询则是加上表2不满足条件的部分 -
子查询
子查询也属于多表查询的一部分,但是在第四章第7小节已经介绍过,这里便不再赘述。
3、事务
事务简介
- 数据库的事务是一种机制,一个操作序列,包含了一组数据库操作命令
- 事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令,要么同时成功,要么同时失败
- 事务是一个不可分割的工作逻辑单元
-- 开启事务 START TRANSACTION;#或者BEGIN; -- 提交事务 COMMIT; -- 回滚事务 ROLLBACK;
事务四大特征
- 原子性:事务是不可分割的最小操作单位,要么同时成功,要么同时失败。
- 一致性:事务完成时,必须使所有数据都保持一致状态。
- 隔离性:多个事物之间,操作的可见性。
- 持久性:事务一旦提交或回滚,它对数据库中数据的改变就是永久的。
注:
MySQL事务默认自动提交(即 @@autocommit 默认为1)
默认为1,代表着每一句命令都是一个事务
-- 查看事物的默认提交方式
SELECT @@autocommit;
-- 0: 手动提交 1: 自动提交
-- 修改事务提交方式
SET @@autocommit = 0;
-- 此处也可以写SET autocommit = 0;但查看事物的默认提交方式的时候不能省略两个@
事务场景模拟
有这样一个bank
表:
两人总共有2000元的存款,现在假设张三要转账200元给李四
不使用事务的情况下,有以下两种可能:
-
转账成功
-- 转账成功 UPDATE bank SET b_money=1000 WHERE b_id=1; UPDATE bank SET b_money=1000 WHERE b_id=2;
转账结果:
-
转账失败
-- 转账失败 UPDATE bank SET b_money=1000 WHERE b_id=1; -- 此时服务器崩了(此处用写错第二句语法来模拟) UPDATE TABLE bank SET b_money=1000 WHERE b_id=2;#该句有语法错误执行不了
转账结果:
这样显然是不符合常识的(至少张三是不会轻易善罢甘休的😠💢)这种中间出现问题的可能性是有的,下面将介绍事务是如何解决这种问题的
使用事务的情况下,有以下两种可能:
-
转账成功
-- 转账成功 SET autocommit=0;#改成手动提交 START TRANSACTION; UPDATE bank SET b_money=1000 WHERE b_id=1; UPDATE bank SET b_money=1000 WHERE b_id=2; COMMIT;#提交,也可以使用 回滚 撤销所有操作 SET autocommit=1;#改回自动提交
转账结果:
-
转账失败
-- 转账失败 SET autocommit=0;#改成手动提交 START TRANSACTION; UPDATE bank SET b_money=1000 WHERE b_id=1; -- 此时服务器崩了(此处用写错第二句语法来模拟,并用ROLLBACK进行回滚操作) ROLLBACK; UPDATE TABLE bank SET b_money=1000 WHERE b_id=2; COMMIT; SET autocommit=1;#改回自动提交
转账结果:
出问题之后通过回滚,保障了千千万万个张三的个人财产不蒙受损失😄
4、索引
-
用处
索引用来排序数据以加快搜索和排序操作的速度(类似于字典的索引)
-
原理
创建一个列的索引后,数据库管理系统将会保存该列内容一个排过序的列表(这一般是主键才有的"特权")。这将大大提升对该列内容进行搜索或排序操作的速度。
-
用法
索引的用法很多,本文作为基础总结,仅在此处列出较为简洁和常用的使用方法
-- 创建索引 CREATE INDEX math_ind ON stu(math);#默认升序 CREATE INDEX eng_ind ON stu(english DESC);#降序 -- 删除索引 ALTER TABLE stu DROP INDEX math_ind; ALTER TABLE stu DROP INDEX eng_ind;
语法:
1.创建索引
CREATE INDEX 索引名 ON 表名(列名 排序方式)
2.删除索引
ALTER TABLE 表名 DROP INDEX 索引名
-
注
1.索引改善检索操作的性能,但降低了数据插入、修改和删除的性能。因为在执行这些操作时,数据库管理系统必须要动态的更新这些索引。
2.索引数据可能要占用大量的存储空间。
3.并非所有数据都适合做索引。取值不多的数据(如学生的班级)不如具有更多可能值的数据(如学号,姓名)更适合建立索引.
4.索引用于数据过滤和数据排序。如果你经常以某种特定的顺序排序数据,则该数据可能较为适合建立索引。
5.可以在索引中定义多个列(如数学分数加上英语分数),则该种索引仅在以数学加英语的顺序排序时有用。如果仅想按数学排序,这种索引便没了用处。
写在后面:
处女之作,万字长文,实属不易。
如有不当或有误之处,请君不吝赐教。