0 前言
以前学习且实践过mysql,但后来用得少,随着岁月更替,对其印象渐浅,所以每次需要用时,都会去再看一眼语法规范,然后才能放心动手操作
然而,在信息爆炸的时代,查语法规范时,检索出来的资料总是五花八门,有时需要看好几篇资料,才能汇总得出完整的、准确的、符合自己语言习惯的信息,这一过程费时费力
鉴于此,本文将根据笔者个人语言习惯,基于mysql8.0.39,整理包括数据、表、库、用户(根据个人使用频率进行的排序)的增、删、改、查基础语法(不涉及数据库安装相关的内容),以节省以后查资料的时间(“自己做的饭,吃着放心”),同时也期待能对读者在mysql基础语法的笔记整理和学习方面有所帮助
(附上mysql官网语法文档链接:https://www.mysqlzh.com/doc/124.html)
1 数据相关
1.1 创建数据
创建数据,其实就是向表中添加/插入数据,默认会向表的最后一条数据之后进行插入
语法:
# (1)插入单条全量数据
# 注意:
# 插入全量数据(表名称后面未指定全量字段)时,即使字段值为null,也需指定null值,
# 否则会报错
# 需要按表结构中字段先后顺序来依次指定字段值
INSERT INTO 数据表名称
VALUES (字段1的值, 字段2的值, ..., 字段N的值);
# (2)插入单条部分数据
# 注意:
# 插入部分数据时,表名称后面指定的字段必须包括非空字段,并需要进行传值;空字段可
# 以指定也可以不指定,指定时为指定值,不指定时为空值或默认值
# 可以在数据表名称后面将字段先后顺序颠倒并对应指定值,但不建议这样做(不规范)
INSERT INTO 数据表名称 (字段a, 字段b, ...)
VALUES (字段a的值, 字段b的值, ...);
# (3)插入多条数据
# 插入多条数据时,不管是全量还是部分数据,依旧需要遵循上面的注意事项
INSERT INTO 数据表名称 (根据全量或部分,选择是否指定字段)
VALUES
(字段1-值1, 字段2-值1, ..., 字段N-值1),
(字段1-值2, 字段2-值2, ..., 字段N-值2),
...
(字段1-值N, 字段2-值N, ..., 字段N-值N);
示例:
假设已经有了一个users表,其建表语句如下:
CREATE TABLE `users` (
`id` SMALLINT(10) NOT NULL COMMENT '用户ID',
`name` VARCHAR(50) DEFAULT NULL COMMENT '用户姓名',
`contact` VARCHAR(100) DEFAULT NULL COMMENT '用户联系方式',
`createTime` DATETIME NOT NULL COMMENT '用户创建时间',
`freeze` TINYINT(1) NOT NULL COMMENT '用户是否被冻结',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `IDX_USERS_CONTACT` (`contact`) USING BTREE,
INDEX `IDX_USERS_NAME` (`name`) USING BTREE
) ENGINE = InnoDB
CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '用户表';
现需要对此表分别实现1条全量数据和2条部分数据的创建
(1)创建1条全量数据
INSERT INTO `users`
VALUES (10000001, '张三', '123456789@qq.com', '2024-08-28 08:08:08', 0);
# (2)创建2条部分数据
# now()是mysql常用的内置函数之一,用于获取当前mysql服务端的时间,其他常用函数可见本文附页5.1章节的内容
INSERT INTO `users` (`id`, `createTime`, `freeze`)
VALUES
(10000002, now(), 0),
(10000003, now(), 0);
验证:
Step1:看执行命令后能否得到Query OK的响应
Step2:查看数据是否成功创建
SELECT * FROM `users`;
1.2 修改数据
语法:
# (1)修改单个字段
UPDATE 数据表名称
SET 字段 = 值
WHERE 筛选条件;
# (2)修改多个字段
UPDATE 数据表名称
SET 字段1 = 值1, 字段2 = 值2, ...
WHERE 筛选条件;
示例:
# (1)将users表中张三的联系方式,修改为18888888888
UPDATE `users`
SET contact = '18888888888'
WHERE name = '张三';
# 查看数据是否修改成功
SELECT * FROM `users`;
# (2)将users表中姓名为null且freeze为0的内容,修改为name='未知',freeze=1
UPDATE `users`
SET name = '未知', freeze = 1
WHERE name is null and freeze = 0;
# 查看数据是否修改成功
SELECT * FROM `users`;
1.3 查询数据
1.3.1 基础查询
语法:
SELECT 字段名称
FROM 数据表名称
WHERE 筛选条件;
(1)字段名称:多个字段可用英文逗号分隔,用*可代表全部字段
(2)运算符:可在SELECT和WHERE后面添加运算符,常见的运算符可见本文附页5.4章节的内容
备注:如何用LIKE模糊查询来查出包含%的数据值?
答案:在代表数据值的%前面加转义符(\)即可
示例:
假设已经有了一个student表,其建表语句以及表数据如下:
CREATE TABLE `student` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '学生ID',
`name` VARCHAR(50) NOT NULL COMMENT '学生姓名',
`class` VARCHAR(10) DEFAULT NULL COMMENT '学生班级',
`chinese` DECIMAL(4,1) NOT NULL COMMENT '语文成绩',
`math` DECIMAL(4,1) NOT NULL COMMENT '数学成绩',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '学生表';
INSERT INTO `student`
VALUES (1, '李伟', '三班', 98.0, 95.0);
INSERT INTO `student`
VALUES (2, '李国栋', '一班', 68.0, 88.0);
INSERT INTO `student`
VALUES (3, '刘小丽', '一班', 76.0, 54.5);
INSERT INTO `student`
VALUES (4, '王思琪', '二班', 34.0, 81.0);
INSERT INTO `student`
VALUES (5, '荆涛', '二班', 88.0, 66.0);
INSERT INTO `student`
VALUES (6, '王勇', '一班', 86.0, 97.5);
INSERT INTO `student`
VALUES (7, '王浩', '三班', 52.0, 41.0);
INSERT INTO `student`
VALUES (8, '张新宇', '三班', 95.0, 98.0);
INSERT INTO `student`
VALUES (9, '王大拿', '二班', 78.0, 84.0);
现需要对此表分别实现全量数据和部分条件数据的查询:
(1)查询student表有多少条数据
SELECT COUNT(*) FROM `student`;
(2)查询student表的全部数据
SELECT * FROM `student`;
(3)查询总共有哪几个班级
SELECT DISTINCT class FROM `student`;
(4)查询三班语文成绩的平均分
SELECT AVG(chinese) FROM `student` WHERE class='三班';
(5)查询一班和二班所有学生的数学成绩最高分
SELECT MAX(math) FROM `student` WHERE class IN ('一班','二班');
(6)查询语文成绩在80-100,且数学成绩在60-100的学生信息
SELECT * FROM `student`
WHERE (chinese BETWEEN 80 AND 100) AND (math BETWEEN 60 AND 100);
1.3.2 高级查询
语法:
SELECT 字段名称
FROM 数据表名称
WHERE 筛选条件
GROUP BY 分组字段名
HAVING 分组后结果的筛选条件
ORDER BY 排序字段名 排序规则(ASC|DESC)
LIMIT 数据行数;
初始化数据:
假设已经有了这三个表,其建表语句以及表数据如下:
CREATE TABLE `dept` (
`deptno` TINYINT not null,
`dname` VARCHAR(14)
);
INSERT INTO `dept` VALUES (10, 'ACCOUNTING');
INSERT INTO `dept` VALUES (20, 'RESEARCH');
INSERT INTO `dept` VALUES (30, 'SALES');
INSERT INTO `dept` VALUES (40, 'OPERATIONS');
INSERT INTO `dept` VALUES (50, 'HR');
INSERT INTO `dept` VALUES (60, NULL);
CREATE TABLE `emp` (
`empno` int,
`ename` VARCHAR(10),
`job` VARCHAR(9),
`mgr` int,
`hiredate` DATE,
`sal` float(7,2),
`comm` float(7,2),
`deptno` TINYINT
);
INSERT INTO `emp` VALUES (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 8000, null, 20);
INSERT INTO `emp` VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 16000, 300, 30);
INSERT INTO `emp` VALUES (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 12500, 500, 30);
INSERT INTO `emp` VALUES (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 29750, null, 20);
INSERT INTO `emp` VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 12500, 1400, 30);
INSERT INTO `emp` VALUES (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 28500, null, 30);
INSERT INTO `emp` VALUES (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 30000, null, 20);
INSERT INTO `emp` VALUES (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 50000, null, 10);
INSERT INTO `emp` VALUES (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 15000, 0, 30);
INSERT INTO `emp` VALUES (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 11000, null, 20);
INSERT INTO `emp` VALUES (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 9500, null, 30);
INSERT INTO `emp` VALUES (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 30000, null, 20);
INSERT INTO `emp` VALUES (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 13000, null, 10);
create table `salgrade`(
`grade` int(11) comment '工资等级',
`losal` int(11) comment '最低工资',
`hisal` int(11) comment '最高工资'
);
INSERT INTO `salgrade` VALUES (1, 7000, 12000);
INSERT INTO `salgrade` VALUES (2, 12010, 14000);
INSERT INTO `salgrade` VALUES (3, 14010, 20000);
INSERT INTO `salgrade` VALUES (4, 20010, 30000);
INSERT INTO `salgrade` VALUES (5, 30010, 99990);
1.3.2.1 group by
在mysql中,group by被广泛应用于需要对数据进行分组统计的查询场景(COUNT(*)其实就相当于一个没有筛选条件的group by)
以实际工作、学习、生活中的场景进行举例:
【工作】对于一个存放了公司的所有员工基本信息的数据表,需要根据不同的业务部门进行分组,查询每个部门有多少人
【学习】对于一个存放了学校所有学生成绩的数据表,需要根据不同的班级来进行分组,查询每个班的各科成绩平均分、最高分、最低分
【生活】对于一个存放了菜市场销售信息的数据表,需要根据粮、油、果、蔬这些不同的商品进行分组,查询每类商品的平均单价、平均销量、总销售额
示例:
查询在员工表(emp表)中,各工作岗位(job)分别有多少人,薪资的最大值、最小值以及平均值分别是多少
SELECT job, COUNT(*) AS `岗位人数` , MAX(sal) AS `岗位最高薪资`, MIN(sal) AS `岗位最低薪资`, AVG(sal) AS `岗位平均薪资`
FROM `emp`
GROUP BY job;
结果:
1.3.2.2 having
having与where的用法类似,都是做条件筛选,不同点:
-
where在group by之前,having在group之后
-
where是先过滤后聚合, having是先聚合后过滤(where是直接做条件筛选,having是根据group by的结果做条件筛选)
-
用AS可以取别名,但where条件一般不能用别名,having条件可以用别名
以实际工作、学习、生活中的场景进行举例:
【工作】对于一个存放了公司的所有员工基本信息的数据表,用group by根据不同的业务部门进行了分组,查出了每个部门有多少人,现需要针对查询结果加筛选:查出部门人数大于50的部门及对应的部门人数
【学习】对于一个存放了学校所有学生成绩的数据表,用group by根据不同的班级进行了分组,查出了每个班的各科成绩平均分、最高分、最低分,现需要针对查询结果加筛选:查出各科成绩平均分>80,最高分=100,最低分<60的班级及对应的各科成绩平均分、最高分、最低分
【生活】对于一个存放了菜市场销售信息的数据表,用group by根据粮、油、果、蔬这些不同的商品进行了分组,查出了每类商品的平均单价、平均销量、总销售额,现需要针对查询结果加筛选:查出每类商品平均单价<8,平均销量>100,总销售额>800的食品及对应的各类商品平均单价、平均销量、总销售额
示例:
查询在员工表(emp表)中,工作岗位(job)人数大于>3、最高薪资<=20000、最低薪资>=10000薪资的岗位以及岗位人数、最高薪资、最低薪资和平均薪资
SELECT job, COUNT(*) AS `岗位人数` , MAX(sal) AS `岗位最高薪资`, MIN(sal) AS `岗位最低薪资`, AVG(sal) AS `岗位平均薪资`
FROM `emp`
GROUP BY job
HAVING `岗位人数` > 3 and `岗位最高薪资` <= 20000 and `岗位最低薪资` >= 10000;
结果:
1.3.2.3 order by + aes|desc
在mysql中,order by被广泛应用于需要对查询结果集(也可以用别名)进行排序的场景,通常需要结合aes(升序)、desc(降序)来进行使用
以实际工作、学习、生活中的场景进行举例:
【工作】对于一个存放了公司的所有员工基本信息的数据表,需要查询每个项目经理的项目回款总额和项目验收数量并降序显示,方便根据业绩进行年终奖发放
【学习】对于一个存放了学校所有学生成绩的数据表,需要查询每个学生的总分并降序显示,方便根据分数进行荣誉奖项发放
【生活】对于一个存放了菜市场销售信息的数据表,需要查询每个商品的单价并升序显示,方便菜市场公告每日最便宜的几个商品
示例:
将员工表(emp表)中各员工薪资(sal)以降序形式进行查询显示
SELECT *
FROM `emp`
ORDER BY sal DESC;
结果:
1.3.2.4 limit & 语法综合实践
在mysql中,limit被广泛应用于获取select查询结果集特定行数的场景(注:limit是起始值默认是从0开始的)
比如:
在web开发中,通常会使用分页查询的方式,来在每一页显示用户所需的多少行数据内容,此时可以用limit来进行处理
在对员工业绩进行排序之后,分别查询出业绩最高和最低的前5名员工信息
示例:
查询在员工表(emp表)中,上级领导(mgr)不为null(除老板之外),工作岗位(job)人数大于>1,平均薪资排名前3名的岗位以及岗位人数、平均薪资
SELECT job, COUNT(*) AS `岗位人数` ,AVG(sal) AS `岗位平均薪资`
FROM `emp`
WHERE mgr is not null
GROUP BY job
HAVING `岗位人数` > 1
ORDER BY `岗位平均薪资` desc
LIMIT 3;
结果:
1.3.5 连接查询
在实际的各类信息系统开发过程中,如果把所有数据都放到一个数据表里面,那么不仅会使insert数据很麻烦,还会影响数据的查询效率以及安全性,所以一般会将各类不同的数据分开到不同的数据表中进行存放,并在数据表中将有关系的字段做关联,形成完善的数据体系
在单个数据表中查询某字段是很容易的,如果要分别查询不同数据表中的不同字段,那就分别对这些数据表进行多次select即可;但如果要将多次select的结果汇总到一起进行显示,那就需要用到连接查询了
连接查询,一般是指将多个数据表通过特定的关联关系连接在一起,并将这些数据表中所需要的各字段汇总得出查询结果
比如:
我在外卖平台点了一份【青椒肉丝】,在外卖系统中,可能会有以下几张表:
(1)商家信息表:存放商家本身的信息,包括商家店名、门店地址、联系电话等数据
(2)商家菜单表:存放商家菜单的信息,包括菜品名称、菜品图片、菜品价格等数据
(3)骑手信息表:存放骑手本身的信息,包括骑手姓名、骑手头像、联系电话等数据
(4)订单信息表:存放订单记录的信息,包括食物列表、订单金额、配送时间等数据
当我点开“配送详情”时,外卖平台就可以将上面四张表关联到一起(商家菜单与商家门店做关联、订单食物列表与商家菜品名称做关联、骑手信息与订单做关联),让我能看到商家店名、食物列表、菜品价格、配送时间等从这些表中汇总得出的信息
连接查询一般分为外连接和内连接两种方式:
-
外连接:一个表与另外一个表之间进行连接
-
内连接:一个表与这个表本身之间进行连接
1.3.5.1 外连接
外连接一般有左连接、右连接以及交差连接三种方式
(1)左连接:left join on
语法:
SELECT 字段名称
FROM 左表 LEFT JOIN 右表
ON 左右两表字段关联关系;
左连接,是以左表数据为基准,通过关联关系,查询出右表中对应的数据,并与左表数据汇总到一起得到查询结果
当左表中的某数据没有一个与之相对应的右表数据时,左表中此数据仍然会显示在查询结果中,右表中对应字段值为空
示例:
在薪资等级表(salgrade)中,通过最低值(losal)和最高值(hisal)的区间,来判断工资属于哪一级(grade)
要求:根据员工表(emp)中薪资(sal)在薪资等级表(salgrade)中哪段区间,来查询得出各员工的工资等级信息
SELECT e.ename AS `姓名`, e.sal AS `薪资`, s.grade AS `薪资等级`
FROM `emp` AS e LEFT JOIN `salgrade` AS s
ON e.sal BETWEEN s.losal AND s.hisal;
结果:
(2)右连接:right join on
语法:
SELECT 字段名称
FROM 左表 RIGHT JOIN 右表
ON 左右两表字段关联关系;
右连接,是以右表数据为基准,通过关联关系,查询出左表中对应的数据,并与左表数据汇总到一起得到查询结果
当右表中的某数据没有一个与之相对应的左表数据时,右表中此数据仍然会显示在查询结果中,左表中对应字段值为空
示例:
将左连接示例
中的LEFT改成RIGHT,观察结果
SELECT e.ename AS `姓名`, e.sal AS `薪资`, s.grade AS `薪资等级`
FROM `emp` AS e RIGHT JOIN `salgrade` AS s
ON e.sal BETWEEN s.losal AND s.hisal;
结果:
(3)交叉连接 cross join
语法:
SELECT 字段名称
FROM 左表 CROSS JOIN 右表;
交叉连接,是将左右两表数据全部都连接一次(笛卡尔积
),可以用where加判断条件
示例:
将部门表(dept)和薪资等级表(salgrade)进行连接,排列组合得到每个部门可能有哪些薪资等级方案
SELECT *
FROM `dept` CROSS JOIN `salgrade`;
结果:
1.3.5.2 内连接
语法:
SELECT 字段名称
FROM 左表 INNER JOIN 右表
ON 左右两表字段关联关系;
注意,对于内连接:
(1)INNER可以省略,即:单写JOIN,不写INNER、LEFT、RIGHT、CROSS,也能代表内连接,但建议写上,这样可读性会更好
(2)ON也可以省略,如果省略,则和CROSS JOIN类似,是得到笛卡尔积,但不建议这么做,笛卡尔积还是用CROSS JOIN,这样可读性会更好
示例:
在员工表(emp)中,存放了每个员工的信息,然而,在一个公司内,员工之间也会存在上下级关系,现需要查询存在上级领导的员工,其上级领导(mgr)是谁
SELECT e1.*, e2.empno AS `领导编号`, e2.ename AS `领导姓名`
FROM `emp` AS e1 INNER JOIN `emp` AS e2
where e1.mgr = e2.empno;
结果:
1.3.5 子查询 + any|all
子查询,其实就是嵌套查询,通常是把某个查询的结果作为一个条件、一个值或者一个临时表来放到where或者from后进行使用,能将复杂的查询逻辑以一种易于理解的方式进行表示
子查询通常可以和any(任一)、all(全部)结合起来进行使用
示例1:
查询出薪资比销售部门(dname=SALES)任何一名员工都要高的所有员工的信息
# 写法1
SELECT *
FROM `emp`
WHERE sal > (SELECT MAX(sal)
FROM `emp`
WHERE deptno = (SELECT deptno
FROM `dept`
WHERE dname = 'SALES'));
# 写法2(使用ALL代替MAX)
SELECT *
FROM `emp`
WHERE sal > ALL(SELECT sal
FROM `emp`
WHERE deptno = (SELECT deptno
FROM `dept`
WHERE dname = 'SALES'));
结果:
备注:嵌套里面的select叫做子查询,嵌套外面的select叫做主查询,执行顺序是:从最里面的子查询开始依次往外进行查询
示例2:
查询每个部门(emp表中deptno字段)的平均薪资(emp表中AVG(sal))是什么薪资等级(salgrade表中grade字段)
# 先对于emp表查询deptno,avg(sal),将查询结果作为临时表,连接salgrade表输出结果
SELECT e.deptno, s.grade
FROM (SELECT deptno,AVG(sal) AS ag FROM `emp` GROUP BY deptno) AS e
INNER JOIN `salgrade` AS s
ON ag BETWEEN losal AND hisal;
1.3.6 union
在mysql中,union操作符用于合并两个或多个select语句的结果集,并返回唯一的结果集(将查询结果进行去重汇总再后返回)
注意,使用union时:
-
要求两个select语句的结果必须是相同字段、相同先后顺序、相同字段列数
-
默认会进行去重(用union all可以保留所有数据,不去重)
语法:
SELECT 字段名称 from 数据表1名称
UNION
SELECT 字段名称 from 数据表2名称;
示例:
假设已经有了2个数据表,分别存放两个学院的教师信息(teacher_medicine表存放医药学院的教师信息,teacher_computer表存放计算机学院的教师信息),其建表语句以及表数据如下:
CREATE TABLE `teacher_medicine` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '教师ID',
`name` VARCHAR(50) NOT NULL COMMENT '教师姓名',
`tno` VARCHAR(50) NOT NULL COMMENT '教师编号',
`class` VARCHAR(10) DEFAULT NULL COMMENT '学生班级',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '医药学院教师表';
INSERT INTO `teacher_medicine`
VALUES (1, '李伟', 't036', '三班');
INSERT INTO `teacher_medicine`
VALUES (2, '李国栋', 't008', '一班');
INSERT INTO `teacher_medicine`
VALUES (3, '刘小丽', 't153', '一班');
INSERT INTO `teacher_medicine`
VALUES (4, '王思琪', 't096', '二班');
CREATE TABLE `teacher_computer` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '教师ID',
`name` VARCHAR(50) NOT NULL COMMENT '教师姓名',
`tno` VARCHAR(50) NOT NULL COMMENT '教师编号',
`class` VARCHAR(10) DEFAULT NULL COMMENT '学生班级',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '计算机学院教师表';
INSERT INTO `teacher_computer`
VALUES (1, '张伟', 't066', '三班');
INSERT INTO `teacher_computer`
VALUES (2, '李国栋', 't008', '一班');
INSERT INTO `teacher_computer`
VALUES (3, '刘思琪', 't099', '一班');
INSERT INTO `teacher_computer`
VALUES (4, '王小丽', 't147', '二班');
现需要查出两个学院的全部教师名称和教师编号
SELECT name, tno from `teacher_medicine`
UNION
SELECT name, tno from `teacher_computer`;
结果:
由于“李国栋”老师在两个学院都任教,所以合并查询后自动去重,只出现一次
1.3.7 exists
在mysql中,exists被广泛应用于检查各种信息是否存在记录的场景,存在则返回1,不存在则返回0
应用场景示例:
# (1)检查数据库/数据表是否存在,不存在则创建数据库/数据表
CREATE TABLE IF NOT EXISTS `test`(`id` int);
# (2)检查select结果集是否存在
SELECT EXISTS(SELECT * FROM `emp` where empno = 666);
# (3)当子查询返回的是一个不确定的值集合时,EXISTS可以作为IN子句的替代,
SELECT * FROM `emp` AS o
WHERE EXISTS (SELECT * FROM `dept` AS d
WHERE d.deptno = o.deptno);
1.4 删除数据(任何删除操作均需谨慎,请勿删数据跑路)
语法:
# (1)删除数据表中指定数据
DELETE FROM 数据表名称
WHERE 筛选条件;
# (2)删除数据表中全部数据
TRUNCATE TABLE 数据表名称;
示例:
# (1)删除users表中联系方式为null的数据
DELETE FROM `users`
WHERE contact is null;
# 查看数据是否删除成功
SELECT * FROM `users`;
# (2)删除users表中全部数据
TRUNCATE TABLE `users`;
# 查看数据是否删除成功
SELECT * FROM `users`;
2 表相关
2.1 创建数据表
语法(常用字段):
CREATE TABLE 数据表名称 (
字段名称1 字段数据类型1 字段约束1 COMMENT '字段描述1',
...
字段名称n 字段数据类型n 字段约束n COMMENT '字段描述n',
表级约束1,
...
表级约束n
) ENGINE 存储引擎
CHARACTER SET 字符集
COLLATE 排序规则
其他规则
COMMENT='表的描述';
(1)建议用反引号(``)包裹数据表名称和字段名称,这样可以更好的支持数据表和字段名称中出现特殊字符
(2)常见的字段数据类型可见本文附页5.2章节的内容
(3)常见的字段约束和表约束可见本文附页5.3章节的内容
(4)存储引擎、字符集、排序规则为非必填
存储引擎、字符集、排序规则如果不设置,则会采取mysql配置文件(my.cnf/my.ini)中的设置;如果在mysql配置文件中也没有设置,则会采取mysql本身的默认设置(此设置根据mysql版本不同而所有差异,具体可以在mysql官方网站查询,但建议在建表语句或者配置文件二选一,这样更清晰)
示例:
创建一个名为users的表,要求:
(1)有5个字段,各字段有类型和约束要求
-
用户ID字段,类型为数值,最大20位,要求字段非空
-
用户姓名字段,类型为字符,最大不超过50位,如果不填值则默认为空
-
用户联系方式字段,类型为字符,最大不超过100位,如果不填值则默认为空
-
用户创建时间字段,类型为日期,要求字段非空
-
用户是否冻结字段,类型为1位数的数值,用0标识未冻结,1标识已冻结,要求字段非空
-
用户ID字段是主键,每个用户的联系方式均唯一,用户的姓名字段加索引,表中所有索引使用B-tree
(2)存储引擎用INNODB、字符集用utf8mb4,排序规则用utf8mb4_general_ci
# 先用use命令选中数据库,才能操作对应的数据表(假设已经有了一个名为lctest的实例库)
use lctest;
# 执行建表语句
CREATE TABLE `users` (
`id` BIGINT(20) NOT NULL COMMENT '用户ID',
`name` VARCHAR(50) DEFAULT NULL COMMENT '用户姓名',
`contact` VARCHAR(100) DEFAULT NULL COMMENT '用户联系方式',
`createTime` DATETIME NOT NULL COMMENT '用户创建时间',
`freeze` TINYINT(1) NOT NULL COMMENT '用户是否被冻结',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `IDX_USERS_CONTACT` (`contact`) USING BTREE,
INDEX `IDX_USERS_NAME` (`name`) USING BTREE
) ENGINE = InnoDB
CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '用户表';
验证:
Step1:看执行命令后能否得到Query OK的响应
Step2:查看数据表是否已创建
SHOW TABLES;
Step3:查看表结构
SHOW CREATE TABLE `users`;
2.2 修改数据表
对于数据表的修改,通常是新增、删除或修改表中的字段名称、字段数据类型或字段约束
语法:
# (1)修改字段名称
ALTER TABLE 数据表名称
CHANGE COLUMN 旧的字段名称 新的字段名称 字段数据类型 COMMENT '字段描述';
# (2)修改字段数据类型
ALTER TABLE 数据表名称
MODIFY COLUMN 字段名称 新的字段数据类型 COMMENT '字段描述';
# (3)修改字段约束
ALTER TABLE 数据表名称
MODIFY COLUMN 字段名称 字段数据类型 新的字段约束 COMMENT '字段描述';
# (4)添加字段
ALTER TABLE 数据表名称
ADD COLUMN 新的字段名称 新的字段数据类型 新的字段约束 COMMENT '新字段的描述',
# (5)删除字段
ALTER TABLE 数据表名称
DROP COLUMN 字段名称;
# (6)添加索引
ALTER TABLE 数据表名称
ADD INDEX 索引名称 (索引字段);
# (7)删除索引
ALTER TABLE 数据表名称
DROP INDEX 索引名称;
# (8)添加主键
ALTER TABLE 数据表名称
ADD PRIMARY KEY (索引字段);
# (9)删除主键
ALTER TABLE 数据表名称
DROP PRIMARY KEY;
示例:
# (1)给users表新增用户年龄字段,类型为数值,最大3位,要求字段非空
ALTER TABLE `users`
ADD COLUMN `age` TINYINT(3) NOT NULL COMMENT '用户年龄';
# 查询是否添加正确
SHOW CREATE TABLE `users`;
# (2)将users表freeze字段的约束条件由NOT NULL改为NOT NULL DEFAULT 0
ALTER TABLE `users`
MODIFY COLUMN `freeze` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '用户是否被冻结';
# 查询是否修改正确
SHOW CREATE TABLE `users`;
# (3)将users表name字段改名为username
ALTER TABLE `users`
CHANGE COLUMN `name` `username` VARCHAR(50) COMMENT '用户姓名';
# 查询是否修改正确
SHOW CREATE TABLE `users`;
# (4)将users表的contact字段的类型由VARCHAR(100)改为VARCHAR(80)
ALTER TABLE `users`
MODIFY COLUMN `contact` VARCHAR(80) COMMENT '用户联系方式';
# 查询是否修改正确
SHOW CREATE TABLE `users`;
# (5)将users表的createTime字段添加索引
ALTER TABLE `users`
ADD INDEX `IDX_USERS_CREATETIME` (`createTime`) USING BTREE;
# 查询是否添加正确
SHOW CREATE TABLE `users`;
2.3 查询数据表
语法:
SHOW CREATE TABLE 数据表名称;
示例:
# 查询表结构
SHOW CREATE TABLE `users`;
2.4 删除数据表(任何删除操作均需谨慎,请勿删表跑路)
语法:
# 删除单个数据表
DROP TABLE 数据表名称1;
# 删除多个数据表
DROP TABLE 数据表1名称,数据表2名称,...,数据表n名称;
示例:
DROP TABLE `users`;
3 库相关
3.1 创建实例库
语法(常用字段):
CREATE DATABASE 实例库名称
DEFAULT CHARACTER SET 字符集
DEFAULT COLLATE 排序规则
实例库名称为必填,字符集、排序规则为非必填
字符集、排序规则如果不设置,则会采取mysql配置文件(my.cnf/my.ini)中的设置;如果在mysql配置文件中也没有设置,则会采取mysql本身的默认设置(此设置根据mysql版本不同而所有差异,具体可以在mysql官方网站查询,但建议在建表语句或者配置文件二选一,这样更清晰)
示例:
创建一个名为lctest的数据库,要求字符集是utf8mb4、排序规则是utf8mb4_0900_ai_ci
CREATE DATABASE lctest
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_0900_ai_ci;
验证:
Step1:看执行命令后能否得到Query OK的响应
Step2:查看数据库是否已创建
SHOW DATABASES;
3.1 修改实例库
修改数据库一般是修改字符集或排序规则,这个操作可能会影响数据的存储和检索,一般很少会用到,通常会在数据库创建时就定义好字符集和排序规则,因此,本文只列举相关语法
ALTER DATABASE 实例库名称
DEFAULT CHARACTER SET 字符集
DEFAULT COLLATE 排序规则
3.3 查询实例库
语法及示例:
SHOW DATABASES;
3.4 删除实例库(任何删除操作均需谨慎,请勿删库跑路)
语法:
DROP DATABASE 实例库名称;
示例:
DROP DATABASE lctest;
验证:
Step1:看执行命令后能否得到Query OK的响应
Step2:查看数据库是否已经被删除
SHOW DATABASES;
4 用户相关
连接数据库,是进行一切数据库相关操作的前提,在数据库的连接命令中,除了数据库服务地址、端口号等信息之外,最关键的就是连接数据库的用户名和密码了,下面将介绍数据库用户相关的增删改查基础语法
4.1 创建用户
语法(常用字段):
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
(1)用户名和密码需妥善保存,且建议采用强密码,避免使用他人易猜测的密码
(2)主机名一般填ip或域名,相当于白名单,代表允许指定的主机连接到此mysql服务。如果需要任何主机都能有权限连接此mysql服务,则可以填写通配符(%)
示例:
# 创建一个名称为lc,密码为lclc_6688的用户
# 仅允许此用户通过数据库服务器本机(localhost)连接数据库
CREATE USER 'lc'@'localhost' IDENTIFIED BY 'lclc_6688';
验证:
Step1:看执行命令后能否得到Query OK的响应
Step2:看能否在数据库服务器本机使用此用户登录连接至数据库
4.2 修改用户
4.2.1 修改用户名、密码
# 使用root或其他管理账户登录连接mysql,然后执行以下命令
# 将用户名从lc改为llcc
RENAME USER 'lc'@'localhost' TO 'llcc'@'localhost';
# 将密码从lclc_6688改为llcc_6688
ALTER USER 'llcc'@'localhost' IDENTIFIED BY 'llcc_6688';
验证:
Step1:看执行命令后能否得到Query OK的响应
Step2:看能否在数据库服务器本机使用新的用户名和密码登录连接至数据库
4.2.2 修改用户权限
语法:
# 新增权限
GRANT 权限项 ON 数据库名.数据表名 TO '用户名'@'主机名';
# 删除权限
REVOKE 权限项 ON 数据库名.数据表名 FROM '用户名'@'主机名';
(1)权限项,包括CREATE(增)、DELETE(删)、UPDATE(改)、SELECT(查)等数据库操作权限,用ALL PRIVILEGES可表示所有权限
(2)数据库名,指的是mysql中的实例库名称,用*可表示所有库
(3)数据表名,指的是实例库对应的数据表名称,用*可表示所有表
(4)用户名,指的是数据库user用户名称
(5)主机名,即:对应user用户的白名单主机名
示例:
# 给llcc这个用户添加此mysql中的所有实例库、所有实例表的所有操作权限
GRANT ALL PRIVILEGES ON *.* TO 'llcc'@'localhost';
# 给llcc这个用户移除mysql中的所有实例库、所有实例表的删除权限
REVOKE DROP,DELETE ON *.* FROM 'llcc'@'localhost';
# 操作之后需要刷新权限,否则不能实时生效
FLUSH PRIVILEGES;
验证:
Step1:看执行命令后能否得到Query OK的响应
Step2:查看llcc用户权限项是否正确
SHOW GRANTS FOR 'llcc'@'localhost';
4.3 查询用户
mysql中的各用户信息也是数据,也会有数据表来进行存储
在mysql中,会有一个名为mysql的实例库,此实例库中有一个名为user的数据表,其存放的就是mysql中各用户信息的数据
# 使用root或其他管理账户登录连接mysql,然后执行以下命令
SELECT * FROM mysql.user;
4.4 删除用户(任何删除操作均需谨慎,请勿删用户跑路)
语法:
DROP USER '用户'@'主机名';
示例:
DROP USER 'llcc'@'localhost';
验证:
Step1:看执行命令后能否得到Query OK的响应
Step2:查询此用户是否还存在于mysql实例库的user表中
# 使用root或其他管理账户登录连接mysql,然后执行以下命令
SELECT * FROM mysql.user;
5 附页
5.1 mysql常用内置函数
函数名称 | 函数标识 | 描述 |
---|---|---|
字符串函数 | CONCAT() | 连接字符串。 |
—— | SUBSTRING() | 提取子字符串。 |
—— | REPLACE() | 替换字符串中的某些字符。 |
—— | LOWER() | 转换为小写。 |
—— | UPPER() | 转换为大写。 |
—— | TRIM() | 去除字符串两端的空格。 |
—— | LPAD() | 左侧填充字符串。 |
—— | RPAD() | 右侧填充字符串。 |
数值函数 | ABS() | 返回绝对值。 |
—— | CEILING() | 返回不小于原数的最小整数。 |
—— | FLOOR() | 返回不大于原数的最大整数。 |
—— | ROUND() | 四舍五入数值。 |
—— | POW() | 求次幂。 |
—— | SQRT() | 计算平方根。 |
日期和时间函数 | NOW() | 返回当前日期和时间。 |
—— | CURDATE() | 返回当前日期。 |
—— | CURTIME() | 返回当前时间。 |
—— | DATEDIFF() | 计算两个日期的差值。 |
—— | DATE_ADD() | 添加日期和时间。 |
—— | DATE_SUB() | 减去日期和时间。 |
—— | DAY() | 从日期中提取天数。 |
—— | MONTH() | 从日期中提取月份。 |
—— | YEAR() | 从日期中提取年份。 |
聚合函数 | COUNT() | 计算数量。 |
—— | SUM() | 计算总和。 |
—— | AVG() | 计算平均值。 |
—— | MAX() | 返回最大值。 |
—— | MIN() | 返回最小值。 |
条件函数 | IF() | 条件表达式。 |
—— | CASE...END | 多条件表达式。 |
其他函数 | VERSION() | 返回MySQL版本。 |
—— | USER() | 返回当前用户名称。 |
—— | DATABASE() | 返回当前数据库名称。 |
5.2 mysql字段常用数据类型
类型名称 | 类型标识 | 描述/最大长度 |
---|---|---|
数值类型 | TINYINT | 很小的整数(8位) |
—— | SMALLINT | 小的整数(16位) |
—— | MEDIUMINT | 中等大小的整数(24位) |
—— | INT | 标准整数(32位) |
—— | BIGINT | 大的整数(64位) |
—— | FLOAT | 单精度浮点数 |
—— | DOUBLE | 双精度浮点数 |
—— | DECIMAL | 定点数,可指定小数位数(例如:DECIMAL(10, 2) 表示总共10位数字,其中2位为小数) |
字符串类型 | CHAR | 固定长度字符串(0-255字符) |
—— | VARCHAR | 可变长度字符串(0-65,535字符) |
—— | TINYTEXT | 小文本(最大长度 255字节) |
—— | TEXT | 文本(最大长度 65,535字节) |
—— | MEDIUMTEXT | 中等大小文本(最大长度 16,777,215字节) |
—— | LONGTEXT | 大文本(最大长度 4,294,967,295字节) |
—— | BINARY | 固定长度二进制字符串 |
—— | VARBINARY | 可变长度二进制字符串 |
日期和时间类型 | DATE | 日期(格式:YYYY-MM-DD ) |
—— | TIME | 时间(格式:HH:MM:SS ) |
—— | DATETIME | 日期和时间(格式:YYYY-MM-DD HH:MM:SS ) |
—— | TIMESTAMP | 时间戳(格式:YYYYMMDDHHMMSS ) |
—— | YEAR | 年份(范围:1901 到 2155 ) |
JSON类型 | JSON | 存储JSON文档 |
枚举和集合类型 | ENUM | 字符串对象的枚举(例如:ENUM('value1', 'value2') ) |
—— | SET | 字符串对象的集合(例如:SET('value1', 'value2') ) |
空间数据类型 | GEOMETRY | 表示几何对象 |
—— | POINT | 表示点 |
—— | LINESTRING | 表示线 |
—— | POLYGON | 表示多边形 |
二进制数据类型 | TINYBLOB | 很小的二进制大对象 |
—— | BLOB | 二进制大对象 |
—— | MEDIUMBLOB | 中等大小的二进制大对象 |
—— | LONGBLOB | 很大的二进制大对象 |
5.3 mysql常用约束类型
约束类型 | 描述 |
---|---|
NOT NULL | 确保列不接受NULL值。 |
NULL | 允许列接受NULL值(默认)。 |
UNIQUE | 强制列的唯一性,不能有重复的值(除了NULL)。 |
PRIMARY KEY | 指定列(或列的组合)作为表的主键,唯一且非空。 |
FOREIGN KEY | 建立当前表和另一个表之间的链接,要求引用的数据必须在另一个表中存在。 |
AUTO_INCREMENT | 用于数值类型的列,自动为新记录生成唯一的递增值。 |
DEFAULT | 指定列的默认值,如果插入记录时未指定值,则使用默认值。 |
CHECK | 确保列的值满足某个条件(MySQL 8.0.16及以上版本支持)。 |
INDEX | 为列创建索引,提高查询效率(不是SQL标准的列约束,但广泛使用)。 |
5.4 mysql常用运算符
类型名称 | 标识 | 描述/用法 |
---|---|---|
算术运算符 | + | 加法 |
—— | - | 减法 |
—— | * | 乘法 |
—— | / | 除法(返回小数结果) |
—— | % | 取模(返回余数) |
—— | // | 整除(返回整数结果) |
比较运算符 | = | 等于(与 == 相同) |
—— | == | 等于 |
—— | != | 不等于(与 <> 相同) |
—— | <> | 不等于 |
—— | > | 大于 |
—— | < | 小于 |
—— | >= | 大于等于 |
—— | <= | 小于等于 |
—— | BETWEEN | 在某个范围内 |
—— | IS NULL | 检查是否为 NULL |
逻辑运算符 | NOT | 逻辑非 |
—— | AND | 逻辑与 |
—— | OR | 逻辑或 |
位运算符 | & | 位与 |
—— | ^ | 位异或 |
—— | ~ | 位取反 |
—— | << | 左移位 |
—— | >> | 右移位 |
字符串连接 | CONCAT() | 连接字符串(或使用 + 运算符) |
赋值运算符 | := | 在存储过程中赋值 |
范围运算符 | IN | 检查值是否在指定范围内 |
模式匹配运算符 | LIKE | 模糊匹配 |
—— | REGEXP /RLIKE | 正则表达式匹配 |
安全的平等比较 | <=> | 安全的等于比较,考虑 NULL 值 |
其他运算符 | DIV | 整除(仅接受整数操作数) |
—— | MOD | 取模(可接受浮点数操作数) |