- 1. 解决之道
- 2. Navicat 安装和使用
- 3. 数据库三层结构-破除 MySQL 神秘
- 4. 数据在数据库中的存储方式
- 5. SQL 语句分类
- 6. 创建数据库
- 7. 查看、删除数据库
- 8. 备份恢复数据库
- 9. 安装 Ecshop 数据库
- 10. 创建表 (按课程大纲顺序)
- 11. Mysql 常用数据类型(列类型)
- 数值型(整数)的基本使用
- 12. 创建表练习
- 13. 修改表-基本介绍
- 14. 修改表-课堂练习
- 15. 数据库 C[create]R[read]U[update]D[delete]语句
- 16. Insert 语句
- 17. update 语句
- 18. delete 语句
- 19. select 语句
- 20. 字符串相关函数
- 21. 数学相关函数
- 22. 时间日期相关函数
- 23. 加密和系统函数
- 24. 流程控制函数
- 25. mysql 表查询—加强
- 26. mysql 多表查询
- 27. mysql 表子查询
- 28. 表复制
- 29. 合并查询
- 30. mysql 表外连接
- 31. mysql 约束
- 32. 自增长
- 33. mysql 索引
- 34. mysql 事务
- 35. mysql 事务隔离级别
- 36. mysql 事务 ACID
- 37. mysql 表类型和存储引擎
- 38. 视图
- 39. Mysql 管理
- 40. 本章作业
1. 解决之道
解决之道-文件、数据库

MySQL 数据库的安装和配置(安装演示)

使用命令行窗口连接 MYSQL 数据库[示意图]

操作示意图

2. Navicat 安装和使用
介绍 : 图形化 MySQL 管理软件


3. 数据库三层结构-破除 MySQL 神秘


4. 数据在数据库中的存储方式

5. SQL 语句分类

6. 创建数据库

# 演示数据库的操作#创建一个名称为 hsp_db01 的数据库。[图形化和指令 演示]#使用指令创建数据库CREATE DATABASE hsp_db01;#删除数据库指令DROP DATABASE hsp_db01#创建一个使用 utf8 字符集的 hsp_db02 数据库CREATE DATABASE hsp_db02 CHARACTER SET utf8#创建一个使用 utf8 字符集,并带校对规则的 hsp_db03 数据库CREATE DATABASE hsp_db03 CHARACTER SET utf8 COLLATE utf8_bin#校对规则 utf8_bin 区分大小 默认 utf8_general_ci 不区分大小写#下面是一条查询的 sql , select 查询 * 表示所有字段 FROM 从哪个表#WHERE 从哪个字段 NAME = 'tom' 查询名字是 tomSELECT *FROM t1WHERE NAME = 'tom'
7. 查看、删除数据库

#演示删除和查询数据库#查看当前数据库服务器中的所有数据库SHOW DATABASES#查看前面创建的 hsp_db01 数据库的定义信息SHOW CREATE DATABASE `hsp_db01`#老师说明 在创建数据库,表的时候,为了规避关键字,可以使用反引号解决#删除前面创建的 hsp_db01 数据库DROP DATABASE hsp_db01
8. 备份恢复数据库

#练习 : database03.sql 备份 hsp_db02 和 hsp_db03 库中的数据,并恢复#备份, 要在 Dos 下执行 mysqldump 指令其实在 mysql 安装目录\bin#这个备份的文件,就是对应的 sql 语句mysqldump -u root -p -B hsp_db02 hsp_db03 > d:\\bak.sqlDROP DATABASE ecshop;#恢复数据库(注意:进入 Mysql 命令行再执行)source d:\\bak.sql#第二个恢复方法, 直接将 bak.sql 的内容放到查询编辑器中,执行
备份恢复数据库的表

9. 安装 Ecshop 数据库

#这是一个 ecshop 的数据库,包括 ecshop 所有的表,请导入到 mysql 数据库中[备份]#进入到 mysql 命令行: source ecshop 备份文件路径#再将 ecshop 整个数据库备份到你的 d:\\ecshop.sql 到 dos 下 :mysqldump -u root -p -B ecshop > d:\\ecshop.sql#将 mysql 的 ecshop 数据库删除, 并通过备份的 d:\\ecshop.sql 恢复#进入 mysql 命令行source d:\\ecshop.sql
10. 创建表 (按课程大纲顺序)

#指令创建表#注意:hsp_db02 创建表时,要根据需保存的数据创建相应的列,并根据数据的类型定义相应的列类型。例:user表 (快速入门案例 create_tab01.sql )#id 整形 [图形化,指令]#name 字符串#password 字符串#birthday 日期CREATE TABLE `user` (id INT, `name` VARCHAR(255), `password` VARCHAR(255), `birthday` DATE)CHARACTER SET utf8 COLLATE utf8_bin ENGINE INNODB;
11. Mysql 常用数据类型(列类型)

数值型(整数)的基本使用

#演示整型的是一个#老韩使用 tinyint 来演示范围 有符号 -128 ~ 127 如果没有符号 0-255#说明: 表的字符集,校验规则, 存储引擎,老师使用默认#1. 如果没有指定 unsinged , 则 TINYINT 就是有符号#2. 如果指定 unsinged , 则 TINYINT 就是无符号 0-255CREATE TABLE t3 (id TINYINT);CREATE TABLE t4 (id TINYINT UNSIGNED);INSERT INTO t3 VALUES(127); #这是非常简单的添加语句SELECT * FROM t3INSERT INTO t4 VALUES(255);SELECT * FROM t4;
型如何定义一个无符号的整数

数值型(bit)的使用

#演示 bit 类型使用#说明#1. bit(m) m 在 1-64#2. 添加数据 范围 按照你给的位数来确定,比如 m = 8 表示一个字节 0~255#3. 显示按照 bit#4. 查询时,仍然可以按照数来查询CREATE TABLE t05 (num BIT(8));INSERT INTO t05 VALUES(255);SELECT * FROM t05;SELECT * FROM t05 WHERE num = 1;
数值型(小数)的基本使用

#演示 decimal 类型、float、double 使用#创建表CREATE TABLE t06 (num1 FLOAT, num2 DOUBLE, num3 DECIMAL(30,20));#添加数据INSERT INTO t06 VALUES(88.12345678912345, 88.12345678912345,88.12345678912345);SELECT * FROM t06;#decimal 可以存放很大的数CREATE TABLE t07 (num DECIMAL(65));INSERT INTO t07 VALUES(8999999933338388388383838838383009338388383838383838383SELECT * FROM t07;CREATE TABLE t08(num BIGINT UNSIGNED)INSERT INTO t08 VALUES(8999999933338388388383838838383009338388383838383838383);SELECT * FROM t08;
字符串的基本使用

#演示字符串类型使用 char varchar#注释的快捷键 shift+ctrl+c , 注销注释 shift+ctrl+r-- CHAR(size)-- 固定长度字符串 最大 255 字符-- VARCHAR(size) 0~65535 字节-- 可变长度字符串 最大 65532 字节 【utf8 编码最大 21844 字符 1-3 个字节用于记录大小】-- 如果表的编码是 utf8 varchar(size) size = (65535-3) / 3 = 21844-- 如果表的编码是 gbk varchar(size) size = (65535-3) / 2 = 32766CREATE TABLE t09 (`name` CHAR(255));CREATE TABLE t10 (`name` VARCHAR(32766)) CHARSET gbk;DROP TABLE t10;
字符串使用细节




#演示字符串类型的使用细节#char(4) 和 varchar(4) 这个 4 表示的是字符,而不是字节, 不区分字符是汉字还是字母CREATE TABLE t11(`name` CHAR(4));INSERT INTO t11 VALUES('韩顺平好');SELECT * FROM t11;CREATE TABLE t12(`name` VARCHAR(4));INSERT INTO t12 VALUES('韩顺平好');INSERT INTO t12 VALUES('ab 北京');SELECT * FROM t12;#如果 varchar 不够用,可以考试使用 mediumtext 或者 longtext, #如果想简单点,可以使用直接使用 textCREATE TABLE t13( content TEXT, content2 MEDIUMTEXT , content3 LONGTEXT);INSERT INTO t13 VALUES('韩顺平教育', '韩顺平教育 100', '韩顺平教育 1000~~');SELECT * FROM t13;
日期类型的基本使用

#演示时间相关的类型#创建一张表, date , datetime , timestampCREATE TABLE t14 (birthday DATE , -- 生日job_time DATETIME, -- 记录年月日 时分秒login_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- 登录时间, 如果希望 login_time 列自动更新, 需要配置);SELECT * FROM t14;INSERT INTO t14(birthday, job_time)VALUES('2022-11-11','2022-11-11 10:10:10'); -- 如果我们更新 t14 表的某条记录,login_time 列会自动的以当前时间进行更新
12. 创建表练习

#创建表的课堂练习-- 字段属性-- Id 整形-- name 字符型-- sex 字符型-- brithday 日期型(date)-- entry_date 日期型 (date)-- job 字符型-- Salary 小数型-- resume 文本型-- 自己一定要练习一把CREATE TABLE `emp` (id INT,`name` VARCHAR(32),sex CHAR(1),brithday DATE,entry_date DATETIME,job VARCHAR(32),salary DOUBLE,`resume` TEXT) CHARSET utf8 COLLATE utf8_bin ENGINE INNODB; -- 添加一条INSERT INTO `emp`VALUES(100, '小妖怪', '男', '2000-11-11','2010-11-10 11:11:11', '巡山的', 3000, '大王叫我来巡山');SELECT * FROM `emp`;
13. 修改表-基本介绍

14. 修改表-课堂练习

#修改表的操作练习-- 员工表 emp 的上增加一个 image 列,varchar 类型(要求在 resume 后面)。ALTER TABLE empADD image VARCHAR(32) NOT NULL DEFAULT ''AFTER RESUMEDESC employee -- 显示表结构,可以查看表的所有列-- 修改 job 列,使其长度为 60。ALTER TABLE empMODIFY job VARCHAR(60) NOT NULL DEFAULT ''-- 删除 sex 列。ALTER TABLE empDROP sex-- 表名改为 employee。RENAME TABLE emp TO employee-- 修改表的字符集为 utf8ALTER TABLE employee CHARACTER SET utf8-- 列名 name 修改为 user_nameALTER TABLE employeeCHANGE `name` `user_name` VARCHAR(64) NOT NULL DEFAULT ''DESC employee
15. 数据库 C[create]R[read]U[update]D[delete]语句

16. Insert 语句
使用 INSERT 语句向表中插入数据。

#练习 insert 语句-- 创建一张商品表 goods (id int , goods_name varchar(10), price double ); -- 添加 2 条记录CREATE TABLE `goods` (id INT ,goods_name VARCHAR(10), -- 长度 10price DOUBLE NOT NULL DEFAULT 100 );-- 添加数据INSERT INTO `goods` (id, goods_name, price)VALUES(10, '华为手机', 2000);INSERT INTO `goods` (id, goods_name, price)VALUES(20, '苹果手机', 3000);SELECT * FROM goods;CREATE TABLE `goods2` (id INT ,goods_name VARCHAR(10), -- 长度 10price DOUBLE NOT NULL DEFAULT 100 );
学员练习:使用 insert 语句向表 employee 中插入 2 个员工的信息。

细节说明
#说明 insert 语句的细节-- 1.插入的数据应与字段的数据类型相同。-- 比如 把 'abc' 添加到 int 类型会错误INSERT INTO `goods` (id, goods_name, price)VALUES('韩顺平', '小米手机', 2000);-- 2. 数据的长度应在列的规定范围内,例如:不能将一个长度为 80 的字符串加入到长度为 40 的列中。INSERT INTO `goods` (id, goods_name, price)VALUES(40, 'vovo 手机 vovo 手机 vovo 手机 vovo 手机 vovo 手机', 3000);-- 3. 在 values 中列出的数据位置必须与被加入的列的排列位置相对应。INSERT INTO `goods` (id, goods_name, price) -- 不对VALUES('vovo 手机',40, 2000);-- 4. 字符和日期型数据应包含在单引号中。INSERT INTO `goods` (id, goods_name, price)VALUES(40, vovo 手机, 3000); -- 错误的 vovo 手机 应该 'vovo 手机'-- 5. 列可以插入空值[前提是该字段允许为空],insert into table value(null)INSERT INTO `goods` (id, goods_name, price)VALUES(40, 'vovo 手机', NULL);-- 6. insert into tab_name (列名..) values (),(),() 形式添加多条记录INSERT INTO `goods` (id, goods_name, price)VALUES(50, '三星手机', 2300),(60, '海尔手机', 1800);-- 7. 如果是给表中的所有字段添加数据,可以不写前面的字段名称INSERT INTO `goods` VALUES(70, 'IBM 手机', 5000);-- 8. 默认值的使用,当不给某个字段值时,如果有默认值就会添加默认值,否则报错-- 如果某个列 没有指定 not null ,那么当添加数据时,没有给定值,则会默认给 null-- 如果我们希望指定某个列的默认值,可以在创建表时指定INSERT INTO `goods` (id, goods_name)VALUES(80, '格力手机');SELECT * FROM goods;INSERT INTO `goods2` (id, goods_name)VALUES(10, '顺平手机');SELECT * FROM goods2;
17. update 语句
使用 update 语句修改表中数据

基本使用

-- 演示 update 语句-- 要求: 在上面创建的 employee 表中修改表中的纪录-- 1. 将所有员工薪水修改为 5000 元。[如果没有带 where 条件,会修改所有的记录,因此要小心]UPDATE employee SET salary = 5000-- 2. 将姓名为 小妖怪 的员工薪水修改为 3000 元。UPDATE employeeSET salary = 3000WHERE user_name = '小妖怪'-- 3. 将 老妖怪 的薪水在原有基础上增加 1000 元INSERT INTO employeeVALUES(200, '老妖怪', '1990-11-11', '2000-11-11 10:10:10', '捶背的', 5000, '给大王捶背', 'd:\\a.jpg');UPDATE employeeSET salary = salary + 1000WHERE user_name = '老妖怪'-- 可以修改多个列的值UPDATE employeeSET salary = salary + 1000 , job = '出主意的'WHERE user_name = '老妖怪'SELECT * FROM employee;
使用细节:

18. delete 语句
使用 delete 语句删除表中数据

-- delete 语句演示-- 删除表中名称为’老妖怪’的记录。DELETE FROM employeeWHERE user_name = '老妖怪';-- 删除表中所有记录, 老师提醒,一定要小心DELETE FROM employee;-- Delete 语句不能删除某一列的值(可使用 update 设为 null 或者 '')UPDATE employee SET job = ''WHERE user_name = '老妖怪';SELECT * FROM employee-- 要删除这个表DROP TABLE employee;
使用细节

19. select 语句
基本语法

注意事项 (创建测试表学生表 )

课堂练习

-- select 语句【重点 难点】CREATE TABLE student(id INT NOT NULL DEFAULT 1,NAME VARCHAR(20) NOT NULL DEFAULT '',chinese FLOAT NOT NULL DEFAULT 0.0,english FLOAT NOT NULL DEFAULT 0.0,math FLOAT NOT NULL DEFAULT 0.0);INSERT INTO student(id,NAME,chinese,english,math) VALUES(1,'韩顺平',89,78,90);INSERT INTO student(id,NAME,chinese,english,math) VALUES(2,'张飞',67,98,56);INSERT INTO student(id,NAME,chinese,english,math) VALUES(3,'宋江',87,78,77);INSERT INTO student(id,NAME,chinese,english,math) VALUES(4,'关羽',88,98,90);INSERT INTO student(id,NAME,chinese,english,math) VALUES(5,'赵云',82,84,67);INSERT INTO student(id,NAME,chinese,english,math) VALUES(6,'欧阳锋',55,85,45);INSERT INTO student(id,NAME,chinese,english,math) VALUES(7,'黄蓉',75,65,30);INSERT INTO student(id,NAME,chinese,english,math) VALUES(8,'韩信',45,65,99);-- 查询表中所有学生的信息。SELECT * FROM student;-- 查询表中所有学生的姓名和对应的英语成绩。SELECT `name`,english FROM student;-- 过滤表中重复数据 distinct 。SELECT DISTINCT english FROM student;-- 要查询的记录,每个字段都相同,才会去重SELECT DISTINCT `name`, english FROM student;
使用表达式对查询的列进行运算

在 select 语句中可使用 as 语句

练习

-- select 语句的使用-- 统计每个学生的总分SELECT `name`, (chinese+english+math) FROM student;-- 在所有学生总分加 10 分的情况SELECT `name`, (chinese + english + math + 10) FROM student;-- 使用别名表示学生分数。SELECT `name` AS '名字', (chinese + english + math + 10) AS total_scoreFROM student;
在 where 子句中经常使用的运算符

使用 where 子句,进行过滤查询

-- select 语句-- 查询姓名为赵云的学生成绩SELECT * FROM studentWHERE `name` = '赵云'-- 查询英语成绩大于 90 分的同学SELECT * FROM studentWHERE english > 90-- 查询总分大于 200 分的所有同学SELECT * FROM studentWHERE (chinese + english + math) > 200-- 查询 math 大于 60 并且(and) id 大于 4 的学生成绩SELECT * FROM studentWHERE math >60 AND id > 4-- 查询英语成绩大于语文成绩的同学SELECT * FROM studentWHERE english > chinese-- 查询总分大于 200 分 并且 数学成绩小于语文成绩,的姓赵的学生.-- 赵% 表示 名字以韩开头的就可以SELECT * FROM studentWHERE (chinese + english + math) > 200 ANDmath < chinese AND `name` LIKE '赵%'-- 查询英语分数在 80-90 之间的同学。SELECT * FROM studentWHERE english >= 80 AND english <= 90;SELECT * FROM studentWHERE english BETWEEN 80 AND 90; -- between .. and .. 是 闭区间-- 查询数学分数为 89,90,91 的同学。SELECT * FROM studentWHERE math = 89 OR math = 90 OR math = 91;SELECT * FROM studentWHERE math IN (89, 90, 91);-- 查询所有姓韩的学生成绩。SELECT * FROM studentWHERE `name` LIKE '韩%'
使用 order by 子句排序查询结果

-- 演示 order by 使用-- 对数学成绩排序后输出【升序】。SELECT * FROM studentORDER BY math;-- 对总分按从高到低的顺序输出 [降序] -- 使用别名排序SELECT `name` , (chinese + english + math) AS total_score FROM studentORDER BY total_score DESC;-- 对姓韩的学生成绩[总分]排序输出(升序) where + order bySELECT `name`, (chinese + english + math) AS total_score FROM studentWHERE `name` LIKE '韩%'ORDER BY total_score;
合计/统计函数
count

-- 演示 mysql 的统计函数的使用-- 统计一个班级共有多少学生?SELECT COUNT(*) FROM student;-- 统计数学成绩大于 90 的学生有多少个?SELECT COUNT(*) FROM studentWHERE math > 90-- 统计总分大于 250 的人数有多少?SELECT COUNT(*) FROM studentWHERE (math + english + chinese) > 250-- count(*) 和 count(列) 的区别-- 解释 :count(*) 返回满足条件的记录的行数-- count(列): 统计满足条件的某列有多少个,但是会排除 为 null 的情况CREATE TABLE t15 (`name` VARCHAR(20));INSERT INTO t15 VALUES('tom');INSERT INTO t15 VALUES('jack');INSERT INTO t15 VALUES('mary');INSERT INTO t15 VALUES(NULL);SELECT * FROM t15;SELECT COUNT(*) FROM t15; -- 4SELECT COUNT(`name`) FROM t15;-- 3-- 演示 sum 函数的使用-- 统计一个班级数学总成绩?SELECT SUM(math) FROM student;-- 统计一个班级语文、英语、数学各科的总成绩SELECT SUM(math) AS math_total_score,SUM(english),SUM(chinese) FROM student;-- 统计一个班级语文、英语、数学的成绩总和SELECT SUM(math + english + chinese) FROM student; -- 统计一个班级语文成绩平均分SELECT SUM(chinese)/ COUNT(*) FROM student;SELECT SUM(`name`) FROM student;-- 演示 avg 的使用-- 练习:-- 求一个班级数学平均分?SELECT AVG(math) FROM student;-- 求一个班级总分平均分SELECT AVG(math + english + chinese) FROM student;-- 演示 max 和 min 的使用-- 求班级最高分和最低分(数值范围在统计中特别有用)SELECT MAX(math + english + chinese), MIN(math + english + chinese)FROM student;-- 求出班级数学最高分和最低分SELECT MAX(math) AS math_high_socre, MIN(math) AS math_low_socreFROM student;
sum

-- 演示 sum 函数的使用-- 统计一个班级数学总成绩?SELECT SUM(math) FROM student;-- 统计一个班级语文、英语、数学各科的总成绩SELECT SUM(math) AS math_total_score,SUM(english),SUM(chinese) FROM student;-- 统计一个班级语文、英语、数学的成绩总和SELECT SUM(math + english + chinese) FROM student;-- 统计一个班级语文成绩平均分SELECT SUM(chinese)/ COUNT(*) FROM student;SELECT SUM(`name`) FROM student;
avg

-- 演示 avg 的使用-- 练习:-- 求一个班级数学平均分?SELECT AVG(math) FROM student;-- 求一个班级总分平均分SELECT AVG(math + english + chinese) FROM student;
max/min

-- 演示 max 和 min 的使用-- 求班级最高分和最低分(数值范围在统计中特别有用)SELECT MAX(math + english + chinese), MIN(math + english + chinese)FROM student;-- 求出班级数学最高分和最低分SELECT MAX(math) AS math_high_socre, MIN(math) AS math_low_socreFROM student;
使用 group by 子句对列进行分组 [先创建测试表]

使用 having 子句对分组后的结果进行过滤


CREATE TABLE dept( /*部门表*/deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,dname VARCHAR(20) NOT NULL DEFAULT "",loc VARCHAR(13) NOT NULL DEFAULT "");INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEW YORK'),(20, 'RESEARCH', 'DALLAS'),(30, 'SALES', 'CHICAGO'),(40, 'OPERATIONS', 'BOSTON');SELECT * FROM dept;-- 员工表CREATE TABLE emp(empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/mgr MEDIUMINT UNSIGNED ,/*上级编号*/hiredate DATE NOT NULL,/*入职时间*/sal DECIMAL(7,2) NOT NULL,/*薪水*/comm DECIMAL(7,2) ,/*红利 奖金*/deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/);-- 添加测试数据INSERT INTO emp VALUES(7369, 'SMITH', 'CLERK', 7902, '1990-12-17', 800.00,NULL , 20),(7499, 'ALLEN', 'SALESMAN', 7698, '1991-2-20', 1600.00, 300.00, 30),(7521, 'WARD', 'SALESMAN', 7698, '1991-2-22', 1250.00, 500.00, 30),(7566, 'JONES', 'MANAGER', 7839, '1991-4-2', 2975.00,NULL,20),(7654, 'MARTIN', 'SALESMAN', 7698, '1991-9-28',1250.00,1400.00,30),(7698, 'BLAKE','MANAGER', 7839,'1991-5-1', 2850.00,NULL,30),(7782, 'CLARK','MANAGER', 7839, '1991-6-9',2450.00,NULL,10),(7788, 'SCOTT','ANALYST',7566, '1997-4-19',3000.00,NULL,20),(7839, 'KING','PRESIDENT',NULL,'1991-11-17',5000.00,NULL,10),(7844, 'TURNER', 'SALESMAN',7698, '1991-9-8', 1500.00, NULL,30),(7900, 'JAMES','CLERK',7698, '1991-12-3',950.00,NULL,30),(7902, 'FORD', 'ANALYST',7566,'1991-12-3',3000.00, NULL,20),(7934,'MILLER','CLERK',7782,'1992-1-23', 1300.00, NULL,10);SELECT * FROM emp;-- 工资级别#工资级别表CREATE TABLE salgrade(grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*工资级别*/losal DECIMAL(17,2) NOT NULL, /* 该级别的最低工资 */hisal DECIMAL(17,2) NOT NULL /* 该级别的最高工资*/);INSERT INTO salgrade VALUES (1,700,1200);INSERT INTO salgrade VALUES (2,1201,1400);INSERT INTO salgrade VALUES (3,1401,2000);INSERT INTO salgrade VALUES (4,2001,3000);INSERT INTO salgrade VALUES (5,3001,9999);SELECT * FROM salgrade;SELECT * FROM dept;SELECT * FROM emp;# 演示 group by + havingGROUP by 用于对查询的结果分组统计, (示意图)-- having 子句用于限制分组显示结果. -- ?如何显示每个部门的平均工资和最高工资-- 老韩分析: avg(sal) max(sal)-- 按照部分来分组查询SELECT AVG(sal), MAX(sal) , deptnoFROM emp GROUP BY deptno;-- 使用数学方法,对小数点进行处理SELECT FORMAT(AVG(sal),2), MAX(sal) , deptnoFROM emp GROUP BY deptno;-- ?显示每个部门的每种岗位的平均工资和最低工资-- 老师分析 1. 显示每个部门的平均工资和最低工资-- 2. 显示每个部门的每种岗位的平均工资和最低工资SELECT AVG(sal), MIN(sal) , deptno, jobFROM emp GROUP BY deptno, job;-- ?显示平均工资低于 2000 的部门号和它的平均工资 // 别名-- 老师分析 [写 sql 语句的思路是化繁为简,各个击破]-- 1. 显示各个部门的平均工资和部门号-- 2. 在 1 的结果基础上,进行过滤,保留 AVG(sal) < 2000-- 3. 使用别名进行过滤SELECT AVG(sal), deptnoFROM emp GROUP BY deptnoHAVING AVG(sal) < 2000;-- 使用别名SELECT AVG(sal) AS avg_sal, deptnoFROM emp GROUP BY deptnoHAVING avg_sal < 2000;
20. 字符串相关函数

-- 演示字符串相关函数的使用 , 使用 emp 表来演示-- CHARSET(str) 返回字串字符集SELECT CHARSET(ename) FROM emp;-- CONCAT (string2 [,... ]) 连接字串, 将多个列拼接成一列SELECT CONCAT(ename, ' 工作是 ', job) FROM emp;-- INSTR (string ,substring ) 返回 substring 在 string 中出现的位置,没有返回 0-- dual 亚元表, 系统表 可以作为测试表使用SELECT INSTR('hanshunping', 'ping') FROM DUAL;-- UCASE (string2 ) 转换成大写SELECT UCASE(ename) FROM emp;-- LCASE (string2 ) 转换成小写SELECT LCASE(ename) FROM emp;-- LEFT (string2 ,length )从 string2 中的左边起取 length 个字符-- RIGHT (string2 ,length ) 从 string2 中的右边起取 length 个字符SELECT LEFT(ename, 2) FROM emp;-- LENGTH (string )string 长度[按照字节]SELECT LENGTH(ename) FROM emp;-- REPLACE (str ,search_str ,replace_str )-- 在 str 中用 replace_str 替换 search_str-- 如果是 manager 就替换成 经理SELECT ename, REPLACE(job,'MANAGER', '经理') FROM emp;-- STRCMP (string1 ,string2 ) 逐字符比较两字串大小SELECT STRCMP('hsp', 'hsp') FROM DUAL;-- SUBSTRING (str , position [,length ])-- 从 str 的 position 开始【从 1 开始计算】,取 length 个字符-- 从 ename 列的第一个位置开始取出 2 个字符SELECT SUBSTRING(ename, 1, 2) FROM emp;-- LTRIM (string2 ) RTRIM (string2 ) TRIM(string)-- 去除前端空格或后端空格SELECT LTRIM(' 韩顺平教育') FROM DUAL;SELECT RTRIM('韩顺平教育 ') FROM DUAL;SELECT TRIM(' 韩顺平教育 ') FROM DUAL;-- 练习: 以首字母小写的方式显示所有员工 emp 表的姓名-- 方法 1-- 思路先取出 ename 的第一个字符,转成小写的-- 把他和后面的字符串进行拼接输出即可SELECT CONCAT(LCASE(SUBSTRING(ename,1,1)), SUBSTRING(ename,2)) AS new_nameFROM emp;SELECT CONCAT(LCASE(LEFT(ename,1)), SUBSTRING(ename,2)) AS new_nameFROM emp;
21. 数学相关函数

-- 演示数学相关函数-- ABS(num) 绝对值SELECT ABS(-10) FROM DUAL;-- BIN (decimal_number )十进制转二进制SELECT BIN(10) FROM DUAL;-- CEILING (number2 ) 向上取整, 得到比 num2 大的最小整数SELECT CEILING(-1.1) FROM DUAL;-- CONV(number2,from_base,to_base) 进制转换-- 下面的含义是 8 是十进制的 8, 转成 2 进制输出SELECT CONV(8, 10, 2) FROM DUAL;-- 下面的含义是 8 是 16 进制的 8, 转成 2 进制输出SELECT CONV(16, 16, 10) FROM DUAL;-- FLOOR (number2 ) 向下取整,得到比 num2 小的最大整数SELECT FLOOR(-1.1) FROM DUAL;-- FORMAT (number,decimal_places ) 保留小数位数(四舍五入)SELECT FORMAT(78.125458,2) FROM DUAL;-- HEX (DecimalNumber ) 转十六进制-- LEAST (number , number2 [,..]) 求最小值SELECT LEAST(0,1, -10, 4) FROM DUAL;-- MOD (numerator ,denominator ) 求余SELECT MOD(10, 3) FROM DUAL;-- RAND([seed]) RAND([seed]) 返回随机数 其范围为 0 ≤ v ≤ 1.0-- 老韩说明-- 1. 如果使用 rand() 每次返回不同的随机数 ,在 0 ≤ v ≤ 1.0-- 2. 如果使用 rand(seed) 返回随机数, 范围 0 ≤ v ≤ 1.0, 如果 seed 不变,-- 该随机数也不变了SELECT RAND() FROM DUAL;SELECT CURRENT_TIMESTAMP() FROM DUAL;
22. 时间日期相关函数






-- 日期时间相关函数-- CURRENT_DATE ( ) 当前日期SELECT CURRENT_DATE() FROM DUAL;-- CURRENT_TIME ( )当前时间SELECT CURRENT_TIME() FROM DUAL;-- CURRENT_TIMESTAMP ( ) 当前时间戳SELECT CURRENT_TIMESTAMP() FROM DUAL;-- 创建测试表 信息表CREATE TABLE mes(id INT ,content VARCHAR(30),send_time DATETIME);-- 添加一条记录INSERT INTO mesVALUES(1, '北京新闻', CURRENT_TIMESTAMP());INSERT INTO mes VALUES(2, '上海新闻', NOW());INSERT INTO mes VALUES(3, '广州新闻', NOW());SELECT * FROM mes;SELECT NOW() FROM DUAL;-- 上应用实例-- 显示所有新闻信息,发布日期只显示 日期,不用显示时间.SELECT id, content, DATE(send_time)FROM mes;-- 请查询在 10 分钟内发布的新闻, 思路一定要梳理一下. SELECT *FROM mesWHERE DATE_ADD(send_time, INTERVAL 10 MINUTE) >= NOW()SELECT *FROM mesWHERE send_time >= DATE_SUB(NOW(), INTERVAL 10 MINUTE)-- 请在 mysql 的 sql 语句中求出 2011-11-11 和 1990-1-1 相差多少天SELECT DATEDIFF('2011-11-11', '1990-01-01') FROM DUAL;-- 请用 mysql 的 sql 语句求出你活了多少天? [练习] 1986-11-11 出生SELECT DATEDIFF(NOW(), '1986-11-11') FROM DUAL;-- 如果你能活 80 岁,求出你还能活多少天.[练习] 1986-11-11 出生-- 先求出活 80 岁 时, 是什么日期 X-- 然后在使用 datediff(x, now()); 1986-11-11->datetime-- INTERVAL 80 YEAR : YEAR 可以是 年月日,时分秒-- '1986-11-11' 可以 date,datetime timestampSELECT DATEDIFF(DATE_ADD('1986-11-11', INTERVAL 80 YEAR), NOW())FROM DUAL;SELECT TIMEDIFF('10:11:11', '06:10:10') FROM DUAL;-- YEAR|Month|DAY| DATE (datetime )SELECT YEAR(NOW()) FROM DUAL;SELECT MONTH(NOW()) FROM DUAL;SELECT DAY(NOW()) FROM DUAL;SELECT MONTH('2013-11-10') FROM DUAL;-- unix_timestamp() : 返回的是 1970-1-1 到现在的秒数SELECT UNIX_TIMESTAMP() FROM DUAL;-- FROM_UNIXTIME() : 可以把一个 unix_timestamp 秒数[时间戳],转成指定格式的日期-- %Y-%m-%d 格式是规定好的,表示年月日-- 意义:在开发中,可以存放一个整数,然后表示时间,通过 FROM_UNIXTIME 转换--SELECT FROM_UNIXTIME(1618483484, '%Y-%m-%d') FROM DUAL;SELECT FROM_UNIXTIME(1618483100, '%Y-%m-%d %H:%i:%s') FROM DUAL;SELECT * FROM mysql.user \G
23. 加密和系统函数

-- 演示加密函数和系统函数-- USER() 查询用户-- 可以查看登录到 mysql 的有哪些用户,以及登录的 IPSELECT USER() FROM DUAL; -- 用户@IP 地址-- DATABASE()查询当前使用数据库名称SELECT DATABASE();-- MD5(str) 为字符串算出一个 MD5 32 的字符串,常用(用户密码)加密-- root 密码是 hsp -> 加密 md5 -> 在数据库中存放的是加密后的密码SELECT MD5('hsp') FROM DUAL;SELECT LENGTH(MD5('hsp')) FROM DUAL;-- 演示用户表,存放密码时,是 md5CREATE TABLE hsp_user(id INT , `name` VARCHAR(32) NOT NULL DEFAULT '', pwd CHAR(32) NOT NULL DEFAULT '');INSERT INTO hsp_userVALUES(100, '韩顺平', MD5('hsp'));SELECT * FROM hsp_user; -- csdnSELECT * FROM hsp_user -- SQL 注入问题WHERE `name`='韩顺平' AND pwd = MD5('hsp')-- PASSWORD(str) -- 加密函数, MySQL 数据库的用户密码就是 PASSWORD 函数加密SELECT PASSWORD('hsp') FROM DUAL; -- 数据库的 *81220D972A52D4C51BB1C37518A2613706220DAC-- select * from mysql.user \G 从原文密码 str 计算并返回密码字符串-- 通常用于对 mysql 数据库的用户密码加密-- mysql.user 表示 数据库.表SELECT * FROM mysql.user
24. 流程控制函数


# 演示流程控制语句# IF(expr1,expr2,expr3) 如果 expr1 为 True ,则返回 expr2 否则返回 expr3SELECT IF(TRUE, '北京', '上海') FROM DUAL;# IFNULL(expr1,expr2) 如果 expr1 不为空 NULL,则返回 expr1,否则返回 expr2SELECT IFNULL( NULL, '韩顺平教育') FROM DUAL;# SELECT CASE WHEN expr1 THEN expr2 WHEN expr3 THEN expr4 ELSE expr5 END; [类似多重分支.]# 如果 expr1 为 TRUE,则返回 expr2,如果 expr2 为 t, 返回 expr4, 否则返回 expr5SELECT CASEWHEN TRUE THEN 'jack' -- jackWHEN FALSE THEN 'tom'ELSE 'mary' END-- 1. 查询 emp 表, 如果 comm 是 null , 则显示 0.0-- 老师说明,判断是否为 null 要使用 is null, 判断不为空 使用 is notSELECT ename, IF(comm IS NULL , 0.0, comm)FROM emp;SELECT ename, IFNULL(comm, 0.0)FROM emp;-- 2. 如果 emp 表的 job 是 CLERK 则显示 职员, 如果是 MANAGER 则显示经理-- 如果是 SALESMAN 则显示 销售人员,其它正常显示SELECT ename, (SELECT CASEWHEN job = 'CLERK' THEN '职员'WHEN job = 'MANAGER' THEN '经理'WHEN job = 'SALESMAN' THEN '销售人员'ELSE job END) AS 'job'FROM emp;SELECT * FROM emp;SELECT * FROM dept;SELECT * FROM salgrade;
25. mysql 表查询—加强
介绍



-- 查询加强-- ■ 使用 where 子句-- ?如何查找 1992.1.1 后入职的员工-- 老师说明: 在 mysql 中,日期类型可以直接比较, 需要注意格式SELECT * FROM empWHERE hiredate > '1992-01-01'-- ■ 如何使用 like 操作符(模糊)-- %: 表示 0 到多个任意字符 _: 表示单个任意字符-- ?如何显示首字符为 S 的员工姓名和工资SELECT ename, sal FROM empWHERE ename LIKE 'S%'-- ?如何显示第三个字符为大写 O 的所有员工的姓名和工资SELECT ename, sal FROM empWHERE ename LIKE '__O%'-- ■ 如何显示没有上级的雇员的情况SELECT * FROM empWHERE mgr IS NULL; -- ■ 查询表结构DESC emp-- 使用 order by 子句-- ?如何按照工资的从低到高的顺序[升序],显示雇员的信息SELECT * FROM empORDER BY sal-- ?按照部门号升序而雇员的工资降序排列 , 显示雇员信息SELECT * FROM empORDER BY deptno ASC , sal DESC;
分页查询

-- 分页查询-- 按雇员的 id 号升序取出, 每页显示 3 条记录,请分别显示 第 1 页,第 2 页,第 3 页-- 第 1 页SELECT * FROM empORDER BY empnoLIMIT 0, 3;-- 第 2 页SELECT * FROM empORDER BY empnoLIMIT 3, 3;-- 第 3 页SELECT * FROM empORDER BY empnoLIMIT 6, 3;-- 推导一个公式SELECT * FROM empORDER BY empnoLIMIT 每页显示记录数 * (第几页-1) , 每页显示记录数-- 测试SELECT job, COUNT(*) FROM emp GROUP BY job;-- 显示雇员总数,以及获得补助的雇员数SELECT COUNT(*) FROM emp WHERE mgr IS NOT NULL;SELECT MAX(sal) - MIN(sal) FROM emp;
使用分组函数和分组子句

-- 增强 group by 的使用-- (1) 显示每种岗位的雇员总数、平均工资。SELECT COUNT(*), AVG(sal), jobFROM empGROUP BY job;-- (2) 显示雇员总数,以及获得补助的雇员数。-- 思路: 获得补助的雇员数 就是 comm 列为非 null, 就是 count(列),如果该列的值为 null, 是-- 不会统计 , SQL 非常灵活,需要我们动脑筋.SELECT COUNT(*), COUNT(comm)FROM emp-- 老师的扩展要求:统计没有获得补助的雇员数SELECT COUNT(*), COUNT(IF(comm IS NULL, 1, NULL))FROM empSELECT COUNT(*), COUNT(*) - COUNT(comm)FROM emp-- (3) 显示管理者的总人数。小技巧:尝试写->修改->尝试[正确的]SELECT COUNT(DISTINCT mgr)FROM emp;-- (4) 显示雇员工资的最大差额。-- 思路: max(sal) - min(sal)SELECT MAX(sal) - MIN(sal)FROM emp;SELECT * FROM emp;select * from dept;-- 应用案例:请统计各个部门 group by 的平均工资 avg,-- 并且是大于 1000 的 having,并且按照平均工资从高到低排序, order by-- 取出前两行记录 limit 0, 2SELECT deptno, AVG(sal) AS avg_salFROM empGROUP BY deptnoHAVING avg_sal > 1000ORDER BY avg_sal DESCLIMIT 0,2
数据分组的总结

26. mysql 多表查询
问题的引出(重点,难点)

说明

多表查询练习

-- 多表查询-- ?显示雇员名,雇员工资及所在部门的名字 【笛卡尔集】/*老韩分析1. 雇员名,雇员工资 来自 emp 表2. 部门的名字 来自 dept 表3. 需求对 emp 和 dept 查询 ename,sal,dname,deptno4. 当我们需要指定显示某个表的列是,需要 表.列表*/SELECT ename,sal,dname,emp.deptnoFROM emp, deptWHERE emp.deptno = dept.deptnoSELECT * FROM emp;SELECT * FROM dept;SELECT * FROM salgrade;-- 老韩小技巧:多表查询的条件不能少于 表的个数-1, 否则会出现笛卡尔集-- ?如何显示部门号为 10 的部门名、员工名和工资SELECT ename,sal,dname,emp.deptnoFROM emp, deptWHERE emp.deptno = dept.deptno AND emp.deptno = 10-- ?显示各个员工的姓名,工资,及其工资的级别-- 思路 姓名,工资 来自 emp 13-- 工资级别 salgrade 5-- 写 sql , 先写一个简单,然后加入过滤条件...select ename, sal, gradefrom emp , salgradewhere sal between losal and hisal;
自连接

-- 多表查询的 自连接-- 思考题: 显示公司员工名字和他的上级的名字-- 老韩分析: 员工名字 在 emp, 上级的名字的名字 emp-- 员工和上级是通过 emp 表的 mgr 列关联-- 这里老师小结:-- 自连接的特点 1. 把同一张表当做两张表使用-- 2. 需要给表取别名 表名 表别名-- 3. 列名不明确,可以指定列的别名 列名 as 列的别名SELECT worker.ename AS '职员名' , boss.ename AS '上级名'FROM emp worker, emp bossWHERE worker.mgr = boss.empno;SELECT * FROM emp;
27. mysql 表子查询
什么是子查询
子查询是指嵌入在其它 sql 语句中的 select 语句,也叫嵌套查询
单行子查询
单行子查询是指只返回一行数据的子查询语句
请思考:如何显示与 SMITH 同一部门的所有员工?
-- 子查询的演示-- 请思考:如何显示与 SMITH 同一部门的所有员工?/*1. 先查询到 SMITH 的部门号得到2. 把上面的 select 语句当做一个子查询来使用*/SELECT deptnoFROM empWHERE ename = 'SMITH'-- 下面的答案.SELECT *FROM empWHERE deptno = (SELECT deptnoFROM empWHERE ename = 'SMITH')
多行子查询
多行子查询指返回多行数据的子查询 使用关键字 **in**

-- 课堂练习:如何查询和部门 10 的工作相同的雇员的-- 名字、岗位、工资、部门号, 但是不含 10 号部门自己的雇员./*1. 查询到 10 号部门有哪些工作2. 把上面查询的结果当做子查询使用*/select distinct jobfrom empwhere deptno = 10;-- 下面语句完整select ename, job, sal, deptnofrom empwhere job in (SELECT DISTINCT jobFROM empWHERE deptno = 10) and deptno <> 10
子查询当做临时表使用

在多行子查询中使用 all 操作符

-- all 和 any 的使用-- 请思考:显示工资比部门 30 的所有员工的工资高的员工的姓名、工资和部门号SELECT ename, sal, deptnoFROM empWHERE sal > ALL(SELECT salFROM empWHERE deptno = 30)-- 可以这样写SELECT ename, sal, deptnoFROM empWHERE sal > (SELECT MAX(sal)FROM empWHERE deptno = 30)
-- 请思考:如何显示工资比部门 30 的其中一个员工的工资高的员工的姓名、工资和部门号SELECT ename, sal, deptnoFROM empWHERE sal > any(SELECT salFROM empWHERE deptno = 30)SELECT ename, sal, deptnoFROM empWHERE sal > (SELECT min(sal)FROM empWHERE deptno = 30)-- 查询 ecshop 中各个类别中,价格最高的商品-- 查询 商品表-- 先得到 各个类别中,价格最高的商品 max + group by cat_id, 当做临时表-- 把子查询当做一张临时表可以解决很多很多复杂的查询select cat_id , max(shop_price)from ecs_goodsgroup by cat_id-- 这个最后答案select goods_id, ecs_goods.cat_id, goods_name, shop_pricefrom (SELECT cat_id , MAX(shop_price) as max_priceFROM ecs_goodsGROUP BY cat_id) temp , ecs_goodswhere temp.cat_id = ecs_goods.cat_id and temp.max_price = ecs_goods.shop_price
在多行子查询中使用 any 操作符

多列子查询

-- 多列子查询-- 请思考如何查询与 allen 的部门和岗位完全相同的所有雇员(并且不含 allen 本人)-- (字段 1, 字段 2 ...) = (select 字段 1,字段 2 from 。。。。)-- 分析: 1. 得到 smith 的部门和岗位SELECT deptno , jobFROM empWHERE ename = 'ALLEN'-- 分析: 2 把上面的查询当做子查询来使用,并且使用多列子查询的语法进行匹配SELECT *FROM empWHERE (deptno , job) = (SELECT deptno , jobFROM empWHERE ename = 'ALLEN') AND ename != 'ALLEN'-- 请查询 和宋江数学,英语,语文-- 成绩 完全相同的学生SELECT *FROM studentWHERE (math, english, chinese) = (SELECT math, english, chineseFROM studentWHERE `name` = '宋江')SELECT * FROM student;
在 from 子句中使用子查询

在 from 子句中使用子查询—课堂小练习

-- 子查询练习-- 请思考:查找每个部门工资高于本部门平均工资的人的资料-- 这里要用到数据查询的小技巧,把一个子查询当作一个临时表使用-- 1. 先得到每个部门的 部门号和 对应的平均工资SELECT deptno, AVG(sal) AS avg_salFROM emp GROUP BY deptno-- 2. 把上面的结果当做子查询, 和 emp 进行多表查询SELECT ename, sal, temp.avg_sal, emp.deptnoFROM emp, (SELECT deptno, AVG(sal) AS avg_salFROM empGROUP BY deptno) tempWHERE emp.deptno = temp.deptno AND emp.sal > temp.avg_sal-- 查找每个部门工资最高的人的详细资料SELECT ename, sal, temp.max_sal, emp.deptnoFROM emp, (SELECT deptno, MAX(sal) AS max_salFROM empGROUP BY deptno) tempWHERE emp.deptno = temp.deptno AND emp.sal = temp.max_sal-- 查询每个部门的信息(包括:部门名,编号,地址)和人员数量,我们一起完成。-- 1. 部门名,编号,地址 来自 dept 表-- 2. 各个部门的人员数量 -》 构建一个临时表SELECT COUNT(*), deptnoFROM empGROUP BY deptno;SELECT dname, dept.deptno, loc , tmp.per_num AS '人数' FROM dept, (SELECT COUNT(*) AS per_num, deptnoFROM empGROUP BY deptno) tmpWHERE tmp.deptno = dept.deptno-- 还有一种写法 表.* 表示将该表所有列都显示出来, 可以简化 sql 语句-- 在多表查询中,当多个表的列不重复时,才可以直接写列名SELECT tmp.* , dname, locFROM dept, (SELECT COUNT(*) AS per_num, deptnoFROM empGROUP BY deptno) tmpWHERE tmp.deptno = dept.deptno
28. 表复制
自我复制数据(蠕虫复制)


-- 表的复制-- 为了对某个 sql 语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据CREATE TABLE my_tab01( id INT,`name` VARCHAR(32),sal DOUBLE,job VARCHAR(32),deptno INT);DESC my_tab01SELECT * FROM my_tab01;-- 演示如何自我复制-- 1. 先把 emp 表的记录复制到 my_tab01INSERT INTO my_tab01(id, `name`, sal, job,deptno)SELECT empno, ename, sal, job, deptno FROM emp;-- 2. 自我复制INSERT INTO my_tab01SELECT * FROM my_tab01;SELECT COUNT(*) FROM my_tab01;-- 如何删除掉一张表重复记录-- 1. 先创建一张表 my_tab02,-- 2. 让 my_tab02 有重复的记录CREATE TABLE my_tab02 LIKE emp; -- 这个语句 把 emp 表的结构(列),复制到 my_tab02DESC my_tab02;INSERT INTO my_tab02SELECT * FROM emp;SELECT * FROM my_tab02;-- 3. 考虑去重 my_tab02 的记录/*思路(1) 先创建一张临时表 my_tmp , 该表的结构和 my_tab02 一样(2) 把 my_tmp 的记录 通过 distinct 关键字 处理后 把记录复制到 my_tmp(3) 清除掉 my_tab02 记录(4) 把 my_tmp 表的记录复制到 my_tab02(5) drop 掉 临时表 my_tmp*/-- (1) 先创建一张临时表 my_tmp , 该表的结构和 my_tab02 一样create table my_tmp like my_tab02-- (2) 把 my_tmp 的记录 通过 distinct 关键字 处理后 把记录复制到 my_tmpinsert into my_tmpselect distinct * from my_tab02;-- (3) 清除掉 my_tab02 记录delete from my_tab02;-- (4) 把 my_tmp 表的记录复制到 my_tab02insert into my_tab02select * from my_tmp;-- (5) drop 掉 临时表 my_tmpdrop table my_tmp;select * from my_tab02;
29. 合并查询
介绍


-- 合并查询SELECT ename,sal,job FROM emp WHERE sal>2500 -- 5SELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3-- union all 就是将两个查询结果合并,不会去重SELECT ename,sal,job FROM emp WHERE sal>2500 -- 5UNION ALLSELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3-- union 就是将两个查询结果合并,会去重SELECT ename,sal,job FROM emp WHERE sal>2500 -- 5UNIONSELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3
30. mysql 表外连接
提出一个问题

外连接


-- 外连接-- 比如:列出部门名称和这些部门的员工名称和工作,-- 同时要求 显示出那些没有员工的部门。-- 使用我们学习过的多表查询的 SQL, 看看效果如何?SELECT dname, ename, jobFROM emp, deptWHERE emp.deptno = dept.deptnoORDER BY dnameSELECT * FROM dept;SELECT * FROM emp;-- 创建 stu/*id name1 Jack2 Tom3 Kity4 nono*/CREATE TABLE stu (id INT, `name` VARCHAR(32));INSERT INTO stu VALUES(1, 'jack'),(2,'tom'),(3, 'kity'),(4, 'nono');SELECT * FROM stu; -- 创建 exam/*id grade1 562 7611 8*/CREATE TABLE exam(id INT,grade INT);INSERT INTO exam VALUES(1, 56),(2,76),(11, 8);SELECT * FROM exam;-- 使用左连接-- (显示所有人的成绩,如果没有成绩,也要显示该人的姓名和 id 号,成绩显示为空)SELECT `name`, stu.id, gradeFROM stu, examWHERE stu.id = exam.id;-- 改成左外连接SELECT `name`, stu.id, gradeFROM stu LEFT JOIN examON stu.id = exam.id;-- 使用右外连接(显示所有成绩,如果没有名字匹配,显示空)-- 即:右边的表(exam) 和左表没有匹配的记录,也会把右表的记录显示出来SELECT `name`, stu.id, gradeFROM stu RIGHT JOIN examON stu.id = exam.id;-- 列出部门名称和这些部门的员工信息(名字和工作),-- 同时列出那些没有员工的部门名。5min-- 使用左外连接实现SELECT dname, ename, jobFROM dept LEFT JOIN empON dept.deptno = emp.deptno-- 使用右外连接实现SELECT dname, ename, jobFROM emp RIGHT JOIN deptON dept.deptno = emp.deptno
课堂练习

31. mysql 约束
基本介绍

primary key(主键)-基本使用


-- 主键使用-- id name emailCREATE TABLE t17(id INT PRIMARY KEY, -- 表示 id 列是主键`name` VARCHAR(32),email VARCHAR(32));-- 主键列的值是不可以重复INSERT INTO t17VALUES(1, 'jack', 'jack@sohu.com');INSERT INTO t17VALUES(2, 'tom', 'tom@sohu.com');INSERT INTO t17VALUES(1, 'hsp', 'hsp@sohu.com');SELECT * FROM t17;-- 主键使用的细节讨论-- primary key 不能重复而且不能为 null。INSERT INTO t17VALUES(NULL, 'hsp', 'hsp@sohu.com');-- 一张表最多只能有一个主键, 但可以是复合主键(比如 id+name)CREATE TABLE t18(id INT PRIMARY KEY, -- 表示 id 列是主键`name` VARCHAR(32), PRIMARY KEY -- 错误的email VARCHAR(32));-- 演示复合主键 (id 和 name 做成复合主键)CREATE TABLE t18(id INT , `name` VARCHAR(32),email VARCHAR(32),PRIMARY KEY (id, `name`) -- 这里就是复合主键);INSERT INTO t18VALUES(1, 'tom', 'tom@sohu.com');INSERT INTO t18VALUES(1, 'jack', 'jack@sohu.com');INSERT INTO t18VALUES(1, 'tom', 'xx@sohu.com'); -- 这里就违反了复合主键SELECT * FROM t18;-- 主键的指定方式 有两种-- 1. 直接在字段名后指定:字段名 primakry key-- 2. 在表定义最后写 primary key(列名);CREATE TABLE t19(id INT ,`name` VARCHAR(32) PRIMARY KEY,email VARCHAR(32));CREATE TABLE t20(id INT ,`name` VARCHAR(32) ,email VARCHAR(32),PRIMARY KEY(`name`) -- 在表定义最后写 primary key(列名));-- 使用 desc 表名,可以看到 primary key 的情况DESC t20 -- 查看 t20 表的结果,显示约束的情况DESC t18
not null(非空)



-- unique 的使用CREATE TABLE t21(id INT UNIQUE , -- 表示 id 列是不可以重复的.`name` VARCHAR(32) ,email VARCHAR(32));INSERT INTO t21VALUES(1, 'jack', 'jack@sohu.com');INSERT INTO t21VALUES(1, 'tom', 'tom@sohu.com');-- unqiue 使用细节-- 1. 如果没有指定 not null , 则 unique 字段可以有多个 null-- 如果一个列(字段), 是 unique not null 使用效果类似 primary keyINSERT INTO t21VALUES(NULL, 'tom', 'tom@sohu.com');SELECT * FROM t21;-- 2. 一张表可以有多个 unique 字段CREATE TABLE t22(id INT UNIQUE ,-- 表示 id 列是不可以重复的.`name` VARCHAR(32) UNIQUE , -- 表示 name 不可以重复email VARCHAR(32));DESC t22
foreign key(外键)



-- 外键演示-- 创建 主表 my_classCREATE TABLE my_class (id INT PRIMARY KEY , -- 班级编号`name` VARCHAR(32) NOT NULL DEFAULT '');-- 创建 从表 my_stuCREATE TABLE my_stu (id INT PRIMARY KEY , -- 学生编号`name` VARCHAR(32) NOT NULL DEFAULT '',class_id INT , -- 学生所在班级的编号-- 下面指定外键关系FOREIGN KEY (class_id) REFERENCES my_class(id))-- 测试数据INSERT INTO my_classVALUES(100, 'java'), (200, 'web');INSERT INTO my_classVALUES(300, 'php');SELECT * FROM my_class;INSERT INTO my_stuVALUES(1, 'tom', 100);INSERT INTO my_stuVALUES(2, 'jack', 200);INSERT INTO my_stuVALUES(3, 'hsp', 300);INSERT INTO my_stuVALUES(4, 'mary', 400); -- 这里会失败...因为 400 班级不存在INSERT INTO my_stuVALUES(5, 'king', NULL); -- 可以, 外键 没有写 not nullSELECT * FROM my_class;-- 一旦建立主外键的关系,数据不能随意删除了DELETE FROM my_classWHERE id = 100;
check

-- 演示 check 的使用-- mysql5.7 目前还不支持 check ,只做语法校验,但不会生效-- 了解-- 学习 oracle, sql server, 这两个数据库是真的生效. -- 测试CREATE TABLE t23 (id INT PRIMARY KEY,`name` VARCHAR(32) ,sex VARCHAR(6) CHECK (sex IN('man','woman')),sal DOUBLE CHECK ( sal > 1000 AND sal < 2000));-- 添加数据INSERT INTO t23VALUES(1, 'jack', 'mid', 1);SELECT * FROM t23;
商店售货系统表设计案例

-- 使用约束的课堂练习CREATE DATABASE shop_db;-- 现有一个商店的数据库 shop_db,记录客户及其购物情况,由下面三个表组成:-- 商品 goods(商品号 goods_id,商品名 goods_name,单价 unitprice,商品类别 category,-- 供应商 provider);-- 客户 customer(客户号 customer_id,姓名 name,住址 address,电邮 email 性别 sex,身份证 card_Id);-- 购买 purchase(购买订单号 order_id,客户号 customer_id,商品号 goods_id,购买数量 nums);-- 1 建表,在定义中要求声明 [进行合理设计]:-- (1)每个表的主外键;-- (2)客户的姓名不能为空值;-- (3)电邮不能够重复;-- (4)客户的性别[男|女] check 枚举..-- (5)单价 unitprice 在 1.0 - 9999.99 之间 check-- 商品 goodsCREATE TABLE goods (goods_id INT PRIMARY KEY,goods_name VARCHAR(64) NOT NULL DEFAULT '',unitprice DECIMAL(10,2) NOT NULL DEFAULT 0CHECK (unitprice >= 1.0 AND unitprice <= 9999.99),category INT NOT NULL DEFAULT 0,provider VARCHAR(64) NOT NULL DEFAULT '');-- 客户 customer(客户号 customer_id,姓名 name,住址 address,电邮 email 性别 sex-- 身份证 card_Id);CREATE TABLE customer(customer_id CHAR(8) PRIMARY KEY, -- 程序员自己决定`name` VARCHAR(64) NOT NULL DEFAULT '',address VARCHAR(64) NOT NULL DEFAULT '',email VARCHAR(64) UNIQUE NOT NULL,sex ENUM('男','女') NOT NULL , -- 这里老师使用的枚举类型, 是生效card_Id CHAR(18));-- 购买 purchase(购买订单号 order_id,客户号 customer_id,商品号 goods_id,-- 购买数量 nums);CREATE TABLE purchase(order_id INT UNSIGNED PRIMARY KEY,customer_id CHAR(8) NOT NULL DEFAULT '', -- 外键约束在后goods_id INT NOT NULL DEFAULT 0 , -- 外键约束在后nums INT NOT NULL DEFAULT 0,FOREIGN KEY (customer_id) REFERENCES customer(customer_id),FOREIGN KEY (goods_id) REFERENCES goods(goods_id));DESC goods;DESC customer;DESC purchase;
32. 自增长
自增长基本介绍 一个问题

自增长使用细节

-- 演示自增长的使用-- 创建表CREATE TABLE t24(id INT PRIMARY KEY AUTO_INCREMENT,email VARCHAR(32)NOT NULL DEFAULT '',`name` VARCHAR(32)NOT NULL DEFAULT '');DESC t24-- 测试自增长的使用INSERT INTO t24VALUES(NULL, 'tom@qq.com', 'tom');INSERT INTO t24 (email, `name`)VALUES('hsp@sohu.com', 'hsp');SELECT * FROM t24;-- 修改默认的自增长开始值ALTER TABLE t25 AUTO_INCREMENT = 100CREATE TABLE t25(id INT PRIMARY KEY AUTO_INCREMENT,email VARCHAR(32)NOT NULL DEFAULT '',`name` VARCHAR(32)NOT NULL DEFAULT '');INSERT INTO t25VALUES(NULL, 'mary@qq.com', 'mary');INSERT INTO t25VALUES(666, 'hsp@qq.com', 'hsp');SELECT * FROM t25;CREATE DATABASE tmp;CREATE TABLE dept( /*部门表*/deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,dname VARCHAR(20) NOT NULL DEFAULT "",loc VARCHAR(13) NOT NULL DEFAULT "") ;#创建表 EMP 雇员CREATE TABLE emp(empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上级编号*/hiredate DATE NOT NULL,/*入职时间*/sal DECIMAL(7,2) NOT NULL,/*薪水*/comm DECIMAL(7,2) NOT NULL,/*红利*/deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/) ;#工资级别表CREATE TABLE salgrade(grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,losal DECIMAL(17,2) NOT NULL,hisal DECIMAL(17,2) NOT NULL);#测试数据INSERT INTO salgrade VALUES (1,700,1200);INSERT INTO salgrade VALUES (2,1201,1400);INSERT INTO salgrade VALUES (3,1401,2000);INSERT INTO salgrade VALUES (4,2001,3000);INSERT INTO salgrade VALUES (5,3001,9999);
33. mysql 索引
索引快速入门

-- 创建测试数据库 tmpCREATE DATABASE tmp;CREATE TABLE dept( /*部门表*/deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,dname VARCHAR(20) NOT NULL DEFAULT "",loc VARCHAR(13) NOT NULL DEFAULT "") ;#创建表 EMP 雇员CREATE TABLE emp(empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上级编号*/hiredate DATE NOT NULL,/*入职时间*/sal DECIMAL(7,2) NOT NULL,/*薪水*/comm DECIMAL(7,2) NOT NULL,/*红利*/deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/) ;#工资级别表CREATE TABLE salgrade(grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,losal DECIMAL(17,2) NOT NULL,hisal DECIMAL(17,2) NOT NULL);#测试数据INSERT INTO salgrade VALUES (1,700,1200);INSERT INTO salgrade VALUES (2,1201,1400);INSERT INTO salgrade VALUES (3,1401,2000);INSERT INTO salgrade VALUES (4,2001,3000);INSERT INTO salgrade VALUES (5,3001,9999);DELIMITER $$#创建一个函数,名字 rand_string,可以随机返回我指定的个数字符串CREATE FUNCTION rand_string(n INT)RETURNS VARCHAR(255) #该函数会返回一个字符串BEGIN#定义了一个变量 chars_str, 类型 varchar(100)#默认给 chars_str 初始值 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ'DECLARE chars_str VARCHAR(100) DEFAULT'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';DECLARE return_str VARCHAR(255) DEFAULT '';DECLARE i INT DEFAULT 0;WHILE i < n DO# concat 函数 : 连接函数 mysql 函数SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));SET i = i + 1;END WHILE;RETURN return_str;END $$#这里我们又自定了一个函数,返回一个随机的部门号CREATE FUNCTION rand_num( )RETURNS INT(5)BEGINDECLARE i INT DEFAULT 0;SET i = FLOOR(10+RAND()*500);RETURN i;END $$#创建一个存储过程, 可以添加雇员CREATE PROCEDURE insert_emp(IN START INT(10),IN max_num INT(10))BEGINDECLARE i INT DEFAULT 0;#set autocommit =0 把 autocommit 设置成 0#autocommit = 0 含义: 不要自动提交SET autocommit = 0; #默认不提交 sql 语句REPEATSET i = i + 1;#通过前面写的函数随机产生字符串和部门编号,然后加入到 emp 表INSERT INTO emp VALUES ((START+i) ,rand_string(6),'SALESMAN',0001,CURDATE(),2000,400,rand_num());UNTIL i = max_numEND REPEAT;#commit 整体提交所有 sql 语句,提高效率COMMIT;END $$#添加 8000000 数据CALL insert_emp(100001,8000000)$$#命令结束符,再重新设置为;DELIMITER ;SELECT COUNT(*) FROM emp;-- 在没有创建索引时,我们的查询一条记录SELECT *FROM empWHERE empno = 1234567-- 使用索引来优化一下, 体验索引的牛-- 在没有创建索引前 , emp.ibd 文件大小 是 524m-- 创建索引后 emp.ibd 文件大小 是 655m [索引本身也会占用空间.]-- 创建 ename 列索引,emp.ibd 文件大小 是 827m-- empno_index 索引名称-- ON emp (empno) : 表示在 emp 表的 empno 列创建索引CREATE INDEX empno_index ON emp (empno)-- 创建索引后, 查询的速度如何SELECT *FROM empWHERE empno = 1234578 -- 0.003s 原来是 4.5s-- 创建索引后,只对创建了索引的列有效SELECT *FROM empWHERE ename = 'PjDlwy' -- 没有在 ename 创建索引时,时间 4.7sCREATE INDEX ename_index ON emp (ename) -- 在 ename 上创建索引
索引的原理

索引的类型

索引使用


-- 演示 mysql 的索引的使用-- 创建索引CREATE TABLE t25 (id INT ,`name` VARCHAR(32));-- 查询表是否有索引SHOW INDEXES FROM t25;-- 添加索引-- 添加唯一索引CREATE UNIQUE INDEX id_index ON t25 (id);-- 添加普通索引方式 1CREATE INDEX id_index ON t25 (id);-- 如何选择-- 1. 如果某列的值,是不会重复的,则优先考虑使用 unique 索引, 否则使用普通索引-- 添加普通索引方式 2ALTER TABLE t25 ADD INDEX id_index (id)-- 添加主键索引CREATE TABLE t26 (id INT ,`name` VARCHAR(32));ALTER TABLE t26 ADD PRIMARY KEY (id)SHOW INDEX FROM t25-- 删除索引DROP INDEX id_index ON t25-- 删除主键索引ALTER TABLE t26 DROP PRIMARY KEY-- 修改索引 , 先删除,在添加新的索引-- 查询索引-- 1. 方式SHOW INDEX FROM t25-- 2. 方式SHOW INDEXES FROM t25-- 3. 方式SHOW KEYS FROM t25-- 4 方式DESC t25
索引课堂练习

小结: 哪些列上适合使用索引

34. mysql 事务
什么是事务


事务和锁

dml : 修改 添加 删除
-- 事务的一个重要的概念和具体操作-- 看一个图[看示意图]-- 演示-- 1. 创建一张测试表CREATE TABLE t27( id INT, `name` VARCHAR(32));-- 2. 开始事务START TRANSACTION-- 3. 设置保存点SAVEPOINT a-- 执行 dml 操作INSERT INTO t27 VALUES(100, 'tom');SELECT * FROM t27;SAVEPOINT b-- 执行 dml 操作INSERT INTO t27 VALUES(200, 'jack');-- 回退到 bROLLBACK TO b-- 继续回退 aROLLBACK TO a-- 如果这样, 表示直接回退到事务开始的状态. ROLLBACKCOMMIT
回退事务

提交事务

事务细节讨论

-- 讨论 事务细节-- 1. 如果不开始事务,默认情况下,dml 操作是自动提交的,不能回滚INSERT INTO t27 VALUES(300, 'milan'); -- 自动提交 commitSELECT * FROM t27-- 2. 如果开始一个事务,你没有创建保存点. 你可以执行 rollback,-- 默认就是回退到你事务开始的状态START TRANSACTIONINSERT INTO t27 VALUES(400, 'king');INSERT INTO t27 VALUES(500, 'scott');ROLLBACK -- 表示直接回退到事务开始的的状态COMMIT;-- 3. 你也可以在这个事务中(还没有提交时), 创建多个保存点.比如: savepoint aaa; -- 执行 dml , savepoint bbb-- 4. 你可以在事务没有提交前,选择回退到哪个保存点-- 5. InnoDB 存储引擎支持事务 , MyISAM 不支持-- 6. 开始一个事务 start transaction, set autocommit=off;
35. mysql 事务隔离级别
事务隔离级别介绍

查看事务隔离级别

事务隔离级别

mysql 的事务隔离级—案例

设置事务隔离级别


-- 演示 mysql 的事务隔离级别-- 1. 开了两个 mysql 的控制台-- 2. 查看当前 mysql 的隔离级别SELECT @@tx_isolation;-- mysql> SELECT @@tx_isolation;-- +-----------------+-- | @@tx_isolation |-- +-----------------+-- | REPEATABLE-READ |-- +-----------------+-- 3.把其中一个控制台的隔离级别设置 Read uncommittedSET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED-- 4. 创建表CREATE TABLE `account`(id INT,`name` VARCHAR(32),money INT);-- 查看当前会话隔离级别SELECT @@tx_isolation-- 查看系统当前隔离级别SELECT @@global.tx_isolation-- 设置当前会话隔离级别SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED-- 设置系统当前隔离级别SET GLOBAL TRANSACTION ISOLATION LEVEL [你设置的级别]
36. mysql 事务 ACID
事务的 acid 特性

事务的课堂练习

37. mysql 表类型和存储引擎
基本介绍

主要的存储引擎/表类型特点

细节说明
我这里重点给大家介绍三种: MyISAM、InnoDB、MEMORY

三种存储引擎表使用案例
-- 表类型和存储引擎-- 查看所有的存储引擎SHOW ENGINES-- innodb 存储引擎,是前面使用过. -- 1. 支持事务 2. 支持外键 3. 支持行级锁-- myisam 存储引擎CREATE TABLE t28 (id INT,`name` VARCHAR(32)) ENGINE MYISAM-- 1. 添加速度快 2. 不支持外键和事务 3. 支持表级锁START TRANSACTION;SAVEPOINT t1INSERT INTO t28 VALUES(1, 'jack');SELECT * FROM t28;ROLLBACK TO t1-- memory 存储引擎-- 1. 数据存储在内存中[关闭了 Mysql 服务,数据丢失, 但是表结构还在]-- 2. 执行速度很快(没有 IO 读写) 3. 默认支持索引(hash 表)CREATE TABLE t29 (id INT,`name` VARCHAR(32)) ENGINE MEMORYDESC t29INSERT INTO t29VALUES(1,'tom'), (2,'jack'), (3, 'hsp');SELECT * FROM t29-- 指令修改存储引擎ALTER TABLE `t29` ENGINE = INNODB
如何选择表的存储引擎

修改存储引擎

38. 视图
看一个需求

基本概念


视图的基本使用

完成前面提出的需求

-- 视图的使用-- 创建一个视图 emp_view01,只能查询 emp 表的(empno、ename, job 和 deptno ) 信息-- 创建视图CREATE VIEW emp_view01ASSELECT empno, ename, job, deptno FROM emp;-- 查看视图DESC emp_view01SELECT * FROM emp_view01;SELECT empno, job FROM emp_view01;-- 查看创建视图的指令SHOW CREATE VIEW emp_view01-- 删除视图DROP VIEW emp_view01;-- 视图的细节-- 1. 创建视图后,到数据库去看,对应视图只有一个视图结构文件(形式: 视图名.frm)-- 2. 视图的数据变化会影响到基表,基表的数据变化也会影响到视图[insert update delete ]-- 修改视图 会影响到基表UPDATE emp_view01SET job = 'MANAGER'WHERE empno = 7369SELECT * FROM emp; -- 查询基表SELECT * FROM emp_view01-- 修改基本表, 会影响到视图UPDATE empSET job = 'SALESMAN'WHERE empno = 7369-- 3. 视图中可以再使用视图 , 比如从 emp_view01 视图中,选出 empno,和 ename 做出新视图DESC emp_view01CREATE VIEW emp_view02ASSELECT empno, ename FROM emp_view01SELECT * FROM emp_view02
视图细节讨论

视图最佳实践

视图课堂练习

-- 视图的课堂练习-- 针对 emp ,dept , 和 salgrade 张三表.创建一个视图 emp_view03,-- 可以显示雇员编号,雇员名,雇员部门名称和 薪水级别[即使用三张表,构建一个视图]/*分析: 使用三表联合查询,得到结果将得到的结果,构建成视图*/CREATE VIEW emp_view03ASSELECT empno, ename, dname, gradeFROM emp, dept, salgradeWHERE emp.deptno = dept.deptno AND(sal BETWEEN losal AND hisal)DESC emp_view03SELECT * FROM emp_view03
39. Mysql 管理
Mysql 用户

创建用户

删除用户

用户修改密码

mysql 中的权限

给用户授权

回收用户授权

权限生效指令

课堂练习题

-- 演示 用户权限的管理-- 创建用户 shunping 密码 123 , 从本地登录CREATE USER 'shunping'@'localhost' IDENTIFIED BY '123'-- 使用 root 用户创建 testdb ,表 newsCREATE DATABASE testdbCREATE TABLE news (id INT ,content VARCHAR(32)); -- 添加一条测试数据INSERT INTO news VALUES(100, '北京新闻');SELECT * FROM news;-- 给 shunping 分配查看 news 表和 添加 news 的权限GRANT SELECT , INSERTON testdb.newsTO 'shunping'@'localhost'-- 可以增加 update 权限GRANT UPDATEON testdb.newsTO 'shunping'@'localhost'-- 修改 shunping 的密码为 abcSET PASSWORD FOR 'shunping'@'localhost' = PASSWORD('abc');-- 回收 shunping 用户在 testdb.news 表的所有权限REVOKE SELECT , UPDATE, INSERT ON testdb.news FROM 'shunping'@'localhost' REVOKE ALL ON testdb.news FROM 'shunping'@'localhost'-- 删除 shunpingDROP USER 'shunping'@'localhost'
细节说明

-- 说明 用户管理的细节-- 在创建用户的时候,如果不指定 Host, 则为% , %表示表示所有 IP 都有连接权限-- create user xxx;CREATE USER jackSELECT `host`, `user` FROM mysql.user-- 你也可以这样指定-- create user 'xxx'@'192.168.1.%' 表示 xxx 用户在 192.168.1.*的 ip 可以登录 mysqlCREATE USER 'smith'@'192.168.1.%'-- 在删除用户的时候,如果 host 不是 %, 需要明确指定 '用户'@'host 值'DROP USER jack -- 默认就是 DROP USER 'jack'@'%'DROP USER 'smith'@'192.168.1.%
40. 本章作业








