MySQL详解

数据库

数据库的好处

​ 1.持久化数据到本地

​ 2.可以实现结构化查询,方便管理

数据库相关概念

​ 1、DB:数据库,保存一组有组织的数据的容器

​ 2、DBMS:数据库管理系统,又称为数据库软件(产品),用于管理DB中的数据

​ 3、SQL:结构化查询语言,用于和DBMS通信的语言

数据库存储数据的特点

​ 1、将数据放到表中,表再放到库中

​ 2、一个数据库中可以有多个表,每个表都有一个的名字,用来标识自己。表名具有唯一性。

​ 3、表具有一些特性,这些特性定义了数据在表中如何存储,类似java中 "类"的设计。

​ 4、表由列组成,我们也称为字段。所有表都是由一个或多个列组成的,每一列类似java 中的"属性"

​ 5、表中的数据是按行存储的,每一行类似于java中的"对象"。

MySQL产品的介绍和安装

MySQL服务的启动和停止

​ 方式一:计算机------右击管理------服务

​ 方式二:通过管理员身份运行

​ net start 服务名(启动服务)

​ net stop 服务名(停止服务)

MySQL服务的登录和退出

​ 方式一:通过mysql自带的客户端

​ 只限于root用户

mysql 复制代码
方式二:通过windows自带的客户端
登录:
mysql 【-h主机名 -P端口号 】-u用户名 -p密码

退出:
exit或ctrl+C

MySQL的常见命令

mysql 复制代码
1.查看当前所有的数据库
show databases;
2.打开指定的库
use 库名
3.查看当前库的所有表
show tables;
4.查看其它库的所有表
show tables from 库名;
5.创建表
create table 表名(

	列名 列类型,
	列名 列类型,
	。。。
);
6.查看表结构
desc 表名;
mysql 复制代码
7.查看服务器的版本
方式一:登录到mysql服务端
select version();
方式二:没有登录到mysql服务端
mysql --version
或
mysql --V

MySQL的语法规范

​ 1.不区分大小写,但建议关键字大写,表名、列名小写

​ 2.每条命令最好用分号结尾

​ 3.每条命令根据需要,可以进行缩进 或换行

​ 4.注释

​ 单行注释:#注释文字

​ 单行注释:-- 注释文字

​ 多行注释:/* 注释文字 */

SQL的语言分类

​ DQL(Data Query Language):数据查询语言

​ select

​ DML(Data Manipulate Language):数据操作语言

​ insert 、update、delete

​ DDL(Data Define Language):数据定义语言

​ create、drop、alter

​ TCL(Transaction Control Language):事务控制语言

​ commit、rollback

SQL的常见命令

复制代码
show databases; 查看所有的数据库
use 库名; 打开指定 的库
show tables ; 显示库中的所有表
show tables from 库名;显示指定库中的所有表
create table 表名(
	字段名 字段类型,	
	字段名 字段类型
); 创建表

desc 表名; 查看指定表的结构
select * from 表名;显示表中的所有数据

MySQL管理

启动mysql服务器:

mysql 复制代码
net start mysql

关闭mysql服务器:

mysql 复制代码
net stop mysql

创建用户

要创建一个新用户,你可以使用以下 SQL 命令:

mysql 复制代码
CREATE USER 'wzx'@'localhost' IDENTIFIED BY '123456';
  • username:用户名。
  • host:指定用户可以从哪些主机连接。例如,localhost 仅允许本地连接,% 允许从任何主机连接。
  • password:用户的密码。

授权权限

创建用户后,你需要授予他们访问权限,使用 GRANT 命令来授予权限:

mysql 复制代码
GRANT privileges ON database_name.* TO 'username'@'host';
  • privileges:所需的权限,如 ALL PRIVILEGESSELECTINSERTUPDATEDELETE 等。
  • database_name.*:表示对某个数据库或表授予权限。database_name.* 表示对整个数据库的所有表授予权限,database_name.table_name 表示对指定的表授予权限。
  • TO 'username'@'host':指定授予权限的用户和主机。

实例

mysql 复制代码
GRANT ALL PRIVILEGES ON test_db.* TO 'wzx'@'localhost';

刷新权限

授予或撤销权限后,需要刷新权限使更改生效:

mysql 复制代码
FLUSH PRIVILEGES;

查看用户权限

要查看特定用户的权限,可以使用以下命令:

mysql 复制代码
SHOW GRANTS FOR 'username'@'host';

实例

mysql 复制代码
SHOW GRANTS FOR 'wzx'@'localhost';

撤销权限

要撤销用户的权限,使用 REVOKE 命令:

mysql 复制代码
REVOKE privileges ON database_name.* FROM 'wzx'@'localhost';

实例

mysql 复制代码
REVOKE ALL PRIVILEGES ON test_db.* FROM 'john'@'localhost';

删除用户

如果需要删除用户,可以使用以下命令:

mysql 复制代码
DROP USER 'wzx'@'localhost';

修改用户密码

要修改用户的密码,可以使用 ALTER USER 命令:

mysql 复制代码
ALTER USER 'username'@'host' IDENTIFIED BY 'new_password';

实例

mysql 复制代码
ALTER USER 'john'@'localhost' IDENTIFIED BY 'newpassword456';

修改用户主机

要更改用户的主机(即允许从哪些主机连接),可以先删除用户,再重新创建一个新的用户。

实例

-- 删除旧用户

mysql 复制代码
DROP USER 'john'@'localhost';

-- 重新创建用户并指定新的主机

mysql 复制代码
CREATE USER 'john'@'%' IDENTIFIED BY 'password123';

创建用户时指定权限

在创建用户时,也可以同时授予权限(在 MySQL 8.0.16 及更高版本):

实例

mysql 复制代码
CREATE USER 'john'@'localhost' IDENTIFIED BY 'password123' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON test_db.* TO 'john'@'localhost';

DQL语言的学习

进阶1:基础查询

​ 语法:

​ SELECT 要查询的东西

​ 【FROM 表名】;

mysql 复制代码
类似于Java中 :System.out.println(要打印的东西);
特点:
①通过select查询完的结果 ,是一个虚拟的表格,不是真实存在
② 要查询的东西 可以是常量值、可以是表达式、可以是字段、可以是函数

进阶2:条件查询

​ 条件查询:根据条件过滤原始表的数据,查询到想要的数据

​ 语法:

​ select

​ 要查询的字段|表达式|常量值|函数

​ from

​ 表

​ where

​ 条件 ;

mysql 复制代码
分类:
一、条件表达式
	示例:salary>10000
	条件运算符:
	> < >= <= = != <>

二、逻辑表达式
示例:salary>10000 && salary<20000

逻辑运算符:

	and(&&):两个条件如果同时成立,结果为true,否则为false
	or(||):两个条件只要有一个成立,结果为true,否则为false
	not(!):如果条件成立,则not后为false,否则为true

三、模糊查询
示例:last_name like 'a%'

进阶3:排序查询

mysql 复制代码
语法:
select
	要查询的东西
from
	表
where 
	条件

order by 排序的字段|表达式|函数|别名 【asc|desc】

-- 2. 多字段排序:先按状态升序,再按金额降序
SELECT order_id, user_id, order_amount, order_status 
FROM order_main 
ORDER BY order_status ASC, order_amount DESC;

-- 5. 按「价格×库存」表达式排序(直接用计算式排序)
SELECT product_name, price, stock, price * stock AS total_value
FROM product 
ORDER BY price * stock DESC;

-- 6. 按「用户名长度」函数排序(LENGTH() 函数返回字符串长度)
SELECT username, phone, LENGTH(username) AS name_length
FROM user_info 
ORDER BY LENGTH(username) ASC;

-- 7. 按别名 total_value 排序(推荐写法,更简洁)
SELECT product_name, price, stock, price * stock AS total_value
FROM product 
ORDER BY total_value DESC;

-- 8. 按别名 amount_div_100 排序
SELECT order_id, order_amount, order_amount / 100 AS amount_div_100
FROM order_main 
ORDER BY amount_div_100 ASC;

进阶4:常见函数

一、单行函数
mysql 复制代码
1、字符函数
    concat拼接
    substr截取子串
    upper转换成大写
    lower转换成小写
    trim去前后指定的空格和字符
    ltrim去左边空格
    rtrim去右边空格
    replace替换
    lpad左填充
    rpad右填充
    instr返回子串第一次出现的索引
    length 获取字节个数
    
    -- 1. concat:拼接字符串(常用:拼接用户名+手机号)
SELECT CONCAT(username, ' - ', phone) AS user_info FROM user_info WHERE user_id = 1;
-- 结果:zhangsan - 13800138000

-- 2. substr:截取子串(语法:substr(字符串, 起始索引, 长度),索引从1开始)
SELECT SUBSTR(product_name, 1, 2) AS short_name FROM product WHERE product_id = 1; -- 截取前2个字符
-- 结果:小米
SELECT SUBSTR(product_name, 3) AS short_name FROM product WHERE product_id = 1;    -- 从第3位截取到末尾
-- 结果:14手机

-- 3. upper:转大写
SELECT UPPER(username) AS upper_name FROM user_info WHERE user_id = 1;
-- 结果:ZHANGSAN

-- 4. lower:转小写
SELECT LOWER('HUAWEIMate60') AS lower_name;
-- 结果:huaweimate60

-- 5. trim:去除前后指定字符(默认去空格,也可指定字符)
SELECT TRIM('   罗技机械键盘   ') AS trim_space; -- 去空格
-- 结果:罗技机械键盘
SELECT TRIM('x' FROM 'xxx金士顿U盘xxx') AS trim_char; -- 去前后的x
-- 结果:金士顿U盘

-- 6. ltrim:去左边空格
SELECT LTRIM('   苹果iPad Pro') AS ltrim_result;
-- 结果:苹果iPad Pro

-- 7. rtrim:去右边空格
SELECT RTRIM('华为Mate60   ') AS rtrim_result;
-- 结果:华为Mate60

-- 8. replace:替换字符(将商品名中的「手机」替换为「智能手机」)
SELECT REPLACE(product_name, '手机', '智能手机') AS new_name FROM product WHERE category = '手机';
-- 结果:小米14智能手机、华为Mate60智能手机

-- 9. lpad:左填充(用指定字符填充到指定长度,长度不足时截断)
SELECT LPAD(price, 8, '0') AS lpad_price FROM product WHERE product_id = 5; -- 价格89.00填充为8位,左边补0
-- 结果:0089.00

-- 10. rpad:右填充(用指定字符填充到指定长度)
SELECT RPAD(product_name, 10, '-') AS rpad_name FROM product WHERE product_id = 4;
-- 结果:罗技机械键盘--

-- 11. instr:返回子串第一次出现的索引(无则返回0)
SELECT INSTR(product_name, 'a') AS index_pos FROM product WHERE product_id = 3;
-- 结果:5(「苹果iPad Pro」中「盘」在第5位)

-- 12. length:获取字节数(utf8mb4中,中文占4字节,数字/字母占1字节)
SELECT LENGTH(product_name) AS byte_count FROM product WHERE product_id = 1;
-- 结果:10(「小米14手机」:小(4)+米(4)+1(1)+4(1)+手(4)+机(4) → 实际计算:4+4+1+1+4+4=18?注:不同字符集可能有差异,以实际运行为准)

2、数学函数
	round 四舍五入
	rand 随机数
	floor向下取整
	ceil向上取整
	mod取余
	truncate截断
	
	# 数学函数
-- 1. round:四舍五入(round(数值, 保留小数位))
SELECT ROUND(price, 1) AS round_price FROM product WHERE product_id = 1; -- 4999.00保留1位小数
-- 结果:4999.0
SELECT ROUND(5999.567); -- 无小数位,四舍五入
-- 结果:5999(或6000,取决于MySQL版本,核心是四舍五入逻辑)

-- 2. rand:生成0~1之间的随机数(常用:生成1~100的随机数)
SELECT RAND() AS random_num; -- 结果示例:0.87654321
SELECT FLOOR(RAND() * 100) + 1 AS random_1_100; -- 1~100的整数随机数

-- 3. floor:向下取整(取小于等于数值的最大整数)
SELECT FLOOR(price / 1000) AS floor_price FROM product WHERE product_id = 2; -- 5999.00/1000=5.999,向下取整
-- 结果:5

-- 4. ceil:向上取整(取大于等于数值的最小整数)
SELECT CEIL(price / 1000) AS ceil_price FROM product WHERE product_id = 2;
-- 结果:6

-- 5. mod:取余(等价于 % 运算符)
SELECT MOD(stock, 7) AS mod_stock FROM product WHERE product_id = 1; -- 100%7=2
-- 结果:2

-- 6. truncate:截断(直接截断小数位,不四舍五入)
SELECT TRUNCATE(5999.999, 1) AS trunc_price; -- 保留1位小数,截断
-- 结果:5999.9

3、日期函数
	now当前系统日期+时间
	curdate当前系统日期
	curtime当前系统时间
	str_to_date 将字符转换成日期
	date_format将日期转换成字符
	-- 1. now:当前系统日期+时间
SELECT NOW() AS current_datetime;
-- 结果示例:2026-01-20 15:30:25

-- 2. curdate:当前系统日期(仅日期)
SELECT CURDATE() AS current_date;
-- 结果示例:2026-01-20

-- 3. curtime:当前系统时间(仅时间)
SELECT CURTIME() AS current_time;
-- 结果示例:15:30:25

-- 4. str_to_date:字符转日期(按指定格式解析,常用:处理前端传入的日期字符串)
SELECT STR_TO_DATE('2026-01-20', '%Y-%m-%d') AS str_to_date;
-- 结果:2026-01-20
SELECT STR_TO_DATE('2026/01/20 15:30', '%Y/%m/%d %H:%i') AS str_to_datetime;
-- 结果:2026-01-20 15:30:00

-- 5. date_format:日期转字符(按指定格式输出,常用:展示友好的日期)
SELECT create_time, DATE_FORMAT(create_time, '%Y年%m月%d日 %H:%i:%s') AS fmt_create_time FROM user_info WHERE user_id = 1;
-- 结果示例:2026-01-20 10:00:00 → 2026年01月20日 10:00:00
	
4、流程控制函数
	if 处理双分支
	case语句 处理多分支
		情况1:处理等值判断
		情况2:处理条件判断
		
		# 流程控制
    -- 1. if:双分支(语法:IF(条件, 满足时返回值, 不满足时返回值))
-- 示例:判断商品价格是否大于1000,标注「高价」/「平价」
SELECT product_name, price, IF(price > 1000, '高价', '平价') AS price_level FROM product;
-- 结果:小米14手机(4999)→ 高价;罗技键盘(299)→ 平价

-- 2. case:多分支(情况1:等值判断)
-- 示例:将订单状态码转换为中文描述
SELECT order_id, order_status,
       CASE order_status
           WHEN 0 THEN '待付款'
           WHEN 1 THEN '已付款'
           WHEN 2 THEN '已发货'
           WHEN 3 THEN '已完成'
           WHEN 4 THEN '已取消'
           ELSE '未知状态'
       END AS status_desc
FROM order_main;
-- 结果:订单1(status=2)→ 已发货;订单3(status=3)→ 已完成

-- 3. case:多分支(情况2:条件判断)
-- 示例:按价格区间分类商品
SELECT product_name, price,
       CASE
           WHEN price > 5000 THEN '高端商品'
           WHEN price > 1000 THEN '中端商品'
           ELSE '低端商品'
       END AS price_category
FROM product;
-- 结果:华为Mate60(5999)→ 高端;小米14(4999)→ 中端;金士顿U盘(89)→ 低端
		
5、其他函数
	version版本
	database当前库
	user当前连接用户
	# 其他函数
-- 1. version:查看MySQL版本
SELECT VERSION() AS mysql_version;
-- 结果示例:8.0.36

-- 2. database:查看当前使用的数据库
SELECT DATABASE() AS current_db;
-- 结果:demo_ecommerce

-- 3. user:查看当前连接的用户
SELECT USER() AS current_use;
-- 结果示例:root@localhost
二、分组函数
mysql 复制代码
	sum 求和
	max 最大值
	min 最小值
	avg 平均值
	count 计数
# count 需要注意的点   COUNT:计数 
-- 示例1:统计商品总数(COUNT(*):统计行数,包含NULL值)
SELECT COUNT(*) AS product_count FROM product;
-- 结果:5
-- 示例2:统计有手机号的用户数(COUNT(字段):排除NULL值)
SELECT COUNT(phone) AS user_with_phone FROM user_info;
-- 结果:3(所有用户都有手机号)
-- 示例3:统计不同订单状态的数量(COUNT(DISTINCT):去重计数)
SELECT COUNT(DISTINCT order_status) AS distinct_status_count FROM order_main;
-- 结果:3(状态2、1、3)

# 综合例句
-- 3. 按订单状态,统计每种状态的订单数、平均金额
SELECT 
  order_status,
  CASE order_status -- 配合流程函数,状态码转中文
    WHEN 0 THEN '待付款'
    WHEN 1 THEN '已付款'
    WHEN 2 THEN '已发货'
    WHEN 3 THEN '已完成'
    WHEN 4 THEN '已取消'
    ELSE '未知'
  END AS status_desc,
  COUNT(*) AS status_count,
  AVG(order_amount) AS status_avg_amount
FROM order_main
GROUP BY order_status; -- 按状态码分组(别名不能用于GROUP BY)
-- 结果:
-- 状态1(已付款):1单,平均7999.00
-- 状态2(已发货):1单,平均5298.00
-- 状态3(已完成):1单,平均89.00

	特点:
	1、以上五个分组函数都忽略null值,除了count(*)
	2、sum和avg一般用于处理数值型
		max、min可以处理字符串,日期,数值,(数值比较,字符按照ASCII/UTF-8进行比较)
		count可以处理任何数据类型
    3、都可以搭配distinct使用,用于统计去重后的结果
	4、count的参数可以支持:
		字段、*、常量值,一般放1
     建议使用 count(*)可以统计null
关键补充(新手必看)!!!!!!
1、COUNT(*) 统计所有行数(包含 NULL 字段),COUNT(字段) 统计该字段非 NULL 的行数,COUNT(DISTINCT 字段) 统计去重后的非 NULL 行数。
2、GROUP BY 后可以跟多个字段(如 GROUP BY a,b),表示按多个字段的组合分组。
3、分组函数不能用在 WHERE 子句中(如 WHERE SUM(price) > 1000 是错误的),必须用 HAVING。
4、GROUP BY 子句中只能用原始字段名,不能用查询别名(如 GROUP BY status_desc 错误)。
5、分组函数(SUM/MAX/MIN/AVG/COUNT)用于统计数据,单独使用时统计全表,配合 GROUP BY 时按指定维度分组统计。
6、HAVING 用于过滤分组结果,需跟在 GROUP BY 后,可使用分组函数;WHERE 用于过滤行,不能用分组函数。
7、实战中最常用的是「GROUP BY + 分组函数 + HAVING」的组合,用于按类别统计并筛选有效数据。

对于avg的小数处理
实战中:
# 使用ROUND
-- 示例1:平均价格四舍五入保留1位小数
SELECT ROUND(AVG(price), 1) AS avg_price_round FROM product;
-- 结果:3857.0(因为原始结果是整数)

# 使用TRUNCATE
-- 示例:外设分类平均价格,截断保留1位小数
SELECT 
  category,
  AVG(price) AS avg_price_original, -- 249.45
  TRUNCATE(AVG(price), 1) AS avg_price_truncate -- 249.4(直接截断,不是249.5)
FROM product
WHERE category = '外设'
GROUP BY category;
# 使用FORMAT
-- 示例:订单平均金额格式化(保留2位,带千分位)
SELECT 
  AVG(order_amount) AS avg_original, -- 4462.00
  FORMAT(AVG(order_amount), 2) AS avg_format -- '4,462.00'(字符串)
FROM order_main;

进阶5:分组查询

​ 语法:

​ select 查询的字段,分组函数

​ from 表

​ group by 分组的字段

mysql 复制代码
特点:
1、可以按单个字段分组
2、和分组函数一同查询的字段最好是分组后的字段
3、分组筛选
		针对的表	位置			关键字
分组前筛选:	原始表		group by的前面		where
分组后筛选:	分组后的结果集	group by的后面		having

4、可以按多个字段分组,字段之间用逗号隔开
5、可以支持排序
6、having后可以支持别名

SELECT
  user_id AS 用户ID,
  SUM(order_amount) AS 消费总额,
  COUNT(*) AS 订单数
FROM order_main
GROUP BY user_id
ORDER BY 消费总额 DESC; 

关键注意事项(新手避坑)
分组字段规则:SELECT 中出现的非聚合函数字段,必须出现在 GROUP BY 中(比如上面的 u.username 必须加在 GROUP BY 里)。
别名使用:GROUP BY 不能用查询别名(如 GROUP BY 商品分类 错误),但 ORDER BY 可以。
NULL 值处理:分组时,NULL 值会被归为一组(比如无订单的用户 wangwu,统计结果为 NULL)。
性能优化:分组前用 WHERE 过滤掉无关数据,减少分组计算量(比如先过滤价格 > 100 的商品)。
总结
GROUP BY 是分组查询的核心,单字段分组适合基础统计,多字段分组适合细粒度统计。
WHERE 过滤原始数据行,HAVING 过滤分组结果,两者结合能精准筛选统计范围。
实战中常结合「联表 + 分组 + 排序」,实现复杂的业务统计(如用户消费分析、商品分类统计)。

进阶6:多表连接查询

复制代码
笛卡尔乘积:如果连接条件省略或无效则会出现
解决办法:添加上连接条件
一、传统模式下的连接 :(内连接)

等值连接------非等值连接

复制代码
1.等值连接的结果 = 多个表的交集
2.n表连接,至少需要n-1个连接条件
3.多个表不分主次,没有顺序要求
4.一般为表起别名,提高阅读性和性能
二、sql语法:通过join关键字实现连接
mysql 复制代码
含义:1999年推出的sql语法
支持:
等值连接、非等值连接 (内连接)
外连接
交叉连接

语法:

select 字段,...
from 表1
【inner|left outer|right outer|cross】join 表2 on  连接条件
【inner|left outer|right outer|cross】join 表3 on  连接条件
【where 筛选条件】
【group by 分组字段】
【having 分组后的筛选条件】
【order by 排序的字段或表达式】

好处:语句上,连接条件和筛选条件实现了分离,简洁明了!
-- 左连接
-- 3. 四表左连接:查询所有用户+所有订单+订单明细+商品信息
SELECT
  u.username AS 用户名,
  o.order_id AS 订单ID,
  p.product_name AS 商品名称,
  oi.quantity AS 购买数量
FROM user_info u
LEFT JOIN order_main o ON u.user_id = o.user_id
LEFT JOIN order_item oi ON o.order_id = oi.order_id
LEFT JOIN product p ON oi.product_id = p.product_id;
-- 运行结果(wangwu无订单,对应字段为NULL):
-- 用户名   | 订单ID | 商品名称       | 购买数量
-- zhangsan | 1      | 小米14手机     | 1
-- zhangsan | 1      | 罗技机械键盘   | 1
-- zhangsan | 3      | 金士顿U盘128G | 1
-- lisi     | 2      | 苹果iPad Pro   | 1
-- wangwu   | NULL   | NULL           | NULL

-- 右连接
-- 1. 基础右连接:查询所有订单+对应的用户(等价于用户表左连接订单表)
SELECT
  o.order_id AS 订单ID,
  u.username AS 用户名,
  o.order_amount AS 订单金额
FROM user_info u
RIGHT JOIN order_main o 
  ON u.user_id = o.user_id;
-- 运行结果(和内连接结果一致,因为所有订单都有对应的用户):
-- 订单ID | 用户名   | 订单金额
-- 1      | zhangsan | 5298.00
-- 2      | lisi     | 7999.00
-- 3      | zhangsan | 89.00
三、自连接

案例:查询员工名和直接上级的名称

sql

mysql 复制代码
SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m ON e.`manager_id`=m.`employee_id`;

-- 自连接查询:每个用户+对应的推荐人名称
SELECT
  u1.user_id AS 用户ID,
  u1.username AS 用户名,
  u2.username AS 推荐人名称  -- 自连接的表别名u2代表推荐人
FROM user_info u1
LEFT JOIN user_info u2 
  ON u1.referrer_id = u2.user_id;  -- 关联条件:推荐人ID=用户ID
-- 运行结果:
-- 用户ID | 用户名   | 推荐人名称
-- 1      | zhangsan | NULL       (无推荐人)
-- 2      | lisi     | zhangsan
-- 3      | wangwu   | lisi

sql

mysql 复制代码
SELECT e.last_name,m.last_name
FROM employees e,employees m 
WHERE e.`manager_id`=m.`employee_id`;

进阶7:子查询

含义:

mysql 复制代码
一条查询语句中又嵌套了另一条完整的select语句,其中被嵌套的select语句,称为子查询或内查询
在外面的查询语句,称为主查询或外查询

特点:

子查询别名:表子查询(返回多行多列)必须起别名(如 t),否则 MySQL 报错;!!!

mysql 复制代码
1、子查询都放在小括号内
2、子查询可以放在from后面、select后面、where后面、having后面,但一般放在条件的右侧
3、子查询优先于主查询执行,主查询使用了子查询的执行结果
4、子查询根据查询结果的行数不同分为以下两类:
① 单行子查询
	结果集只有一行
	一般搭配单行操作符使用:> < = <> >= <= 
	非法使用子查询的情况:
	a、子查询的结果为一组值
	b、子查询的结果为空
	
② 多行子查询
	结果集有多行
	一般搭配多行操作符使用:any、all、in、not in
	in: 属于子查询结果中的任意一个就行
	any和all往往可以用其他查询代替
-- any 和 all的应用
	-- 3. 查询「订单金额大于任意一个已完成订单金额」的订单(ANY)
SELECT order_id, order_amount
FROM order_main
WHERE order_amount > ANY (
  -- 子查询:查所有已完成订单的金额(返回列:89.00)
  SELECT order_amount FROM order_main WHERE order_status = 3
);
-- 运行结果(金额>89.00的订单):
-- order_id | order_amount
-- 1        | 5298.00
-- 2        | 7999.00

-- 补充:ALL 表示「大于所有」,比如 > ALL (SELECT ...) 会只返回7999.00的订单


-- 行子查询
-- 2. 查询「每个用户的最大金额订单」(行子查询+分组)
SELECT
  order_id AS 订单ID,
  user_id AS 用户ID,
  order_amount AS 订单金额
FROM order_main o1
WHERE (user_id, order_amount) IN (
  -- 子查询:按用户分组,查每个用户的最大金额(返回多行两列)
  SELECT user_id, MAX(order_amount) FROM order_main GROUP BY user_id
);
-- 运行结果:
-- 订单ID | 用户ID | 订单金额
-- 1      | 1      | 5298.00
-- 2      | 2      | 7999.00


-- 表子查询
-- 1. 查询「订单金额>5000」的订单+对应的用户信息(子查询作为数据源)
SELECT
  t.order_id AS 订单ID,
  u.username AS 用户名,
  t.order_amount AS 订单金额
FROM (
  -- 子查询:筛选金额>5000的订单(返回多行多列的临时表)
  SELECT order_id, user_id, order_amount FROM order_main WHERE order_amount > 5000
) t  -- 给子查询起别名t
JOIN user_info u ON t.user_id = u.user_id;  -- 临时表关联用户表
-- 运行结果:
-- 订单ID | 用户名   | 订单金额
-- 1      | zhangsan | 5298.00
-- 2      | lisi     | 7999.00


-- 关联子查询
-- 1. 查询「每个用户的最大金额订单」(关联子查询)
SELECT
  o1.order_id AS 订单ID,
  o1.user_id AS 用户ID,
  o1.order_amount AS 订单金额
FROM order_main o1
WHERE o1.order_amount = (
  -- 子查询:查当前用户(o1.user_id)的最大订单金额(依赖外层字段)
  SELECT MAX(o2.order_amount) FROM order_main o2 WHERE o2.user_id = o1.user_id
);
-- 运行结果:
-- 订单ID | 用户ID | 订单金额
-- 1      | 1      | 5298.00
-- 2      | 2      | 7999.00

进阶8:分页查询

应用场景:

复制代码
实际的web项目中需要根据用户的需求提交对应的分页查询的sql语句

语法:

mysql 复制代码
select 字段|表达式,...
from 表
【where 条件】
【group by 分组字段】
【having 条件】
【order by 排序的字段】
limit 【起始的条目索引,】条目数;

特点:

mysql 复制代码
1.起始条目索引从0开始

2.limit子句放在查询语句的最后

3.公式:select * from  表 limit (page-1)*sizePerPage,sizePerPage
假如:
每页显示条目数sizePerPage
要显示的页数 page
分页查询优化技巧:

1、基于主键/索引排序分页(推荐)

mysql 复制代码
-- 优化:用主键(product_id)排序,避免全表扫描
-- 场景:商品表大偏移量分页(模拟第100页,每页10条)
SELECT
  product_id AS 商品ID,
  product_name AS 商品名称,
  price AS 价格
FROM product
WHERE product_id > (100-1)*10  -- 偏移量转换为主键筛选:(页码-1)*条数
ORDER BY product_id ASC
LIMIT 10;  -- 只取10条,无需大偏移量

2、避免select,只查询必要字段*

mysql 复制代码
-- 反例:SELECT * 会查所有字段,性能差
SELECT * FROM product LIMIT 10000, 10;

-- 正例:只查需要的字段,减少数据传输
SELECT product_id, product_name, price FROM product 
ORDER BY product_id ASC LIMIT 10000, 10;

3、先分页再分表(减少联表数据量)

应用场景:

某电商平台的后台管理系统,有一个「订单列表」功能:

  • 运营人员需要查看订单信息,每页显示 20 条;
  • 订单表(order_main)有1000 万条历史数据,且每天新增 10 万 + 订单;
  • 列表需要展示的字段:订单 ID、下单用户昵称、订单金额、支付状态、商品名称、收货人电话(这些字段分布在 order_mainuser_infoorder_itemproductuser_address 5 张表中)。
mysql 复制代码
-- 优化:先对主表分页,再联表查询详情(适合大表)
SELECT
  o.order_id, u.username, o.order_amount
FROM (
  -- 子查询:先对订单表分页(只查主键)
  SELECT order_id, user_id, order_amount 
  FROM order_main 
  ORDER BY order_id ASC 
  LIMIT 0, 2  -- 第1页,每页2条
) o
JOIN user_info u ON o.user_id = u.user_id;  -- 再联表查用户名

关键注意事项

  1. 分页必须排序 :如果不加 ORDER BY,MySQL 返回的是「随机结果」,分页翻页会出现数据重复 / 缺失;
  2. 偏移量计算:偏移量 = (页码 - 1) × 每页条数(比如第 3 页、每页 10 条 → 偏移量 = 20);
  3. 大偏移量优化 :避免直接用 LIMIT 10000, 10,优先用「主键 / 索引筛选 + LIMIT 条数」;
分页查询关键说明:
  • 主键 product_id 是自增的,第 1000 页的起始主键值 = 偏移量(9990);
  • 如果主键不是从 1 开始,或有删除数据导致主键不连续,可先查「上一页最后一条的主键」:
mysql 复制代码
-- ❶ 传统低效写法(不推荐):大偏移量导致全表扫描
SELECT
  product_id, product_name, price, stock
FROM product
ORDER BY product_id ASC  -- 必须按主键排序(和筛选条件一致)
LIMIT 9990, 10;  -- 第1000页,每页10条 → 偏移量9990

-- ❷ 优化写法(推荐):主键筛选 + LIMIT 条数
SELECT
  product_id, product_name, price, stock
FROM product
WHERE product_id > 9990  -- 直接定位到起始主键(偏移量=9990)
ORDER BY product_id ASC  -- 按主键排序(保证有序)
LIMIT 10;  -- 只取10条,无需大偏移量
  1. NULL 值处理 :左连接分页时,用 IFNULL() 替换 NULL(如 IFNULL(SUM(amount), 0))。
sql查询优化:

1、按需查询字段,减少网络IO消耗

2、避免使用select*,减少Mysql优化器负担

3、查询的字段尽量保证索引覆盖

4、借助nosql缓存数据环节Mysql数据库的压力

进阶9:联合查询

引入:

union 联合、合并

union all 不会去重, union会自动去重

语法:

mysql 复制代码
select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】
select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】
select 字段|常量|表达式|函数 【from 表】 【where 条件】 union  【all】
.....
select 字段|常量|表达式|函数 【from 表】 【where 条件】

-- ❶ UNION ALL(不查重,性能高):合并高价商品(>5000)和高库存商品(>200)
SELECT
  product_id AS 商品ID,
  product_name AS 商品名称,
  price AS 价格,
  stock AS 库存,
  '高价商品' AS 标签  -- 自定义标签,区分数据来源
FROM product
WHERE price > 5000

UNION ALL  -- 合并第二个查询结果

SELECT
  product_id AS 商品ID,
  product_name AS 商品名称,
  price AS 价格,
  stock AS 库存,
  '高库存商品' AS 标签
FROM product
WHERE stock >= 200;

-- 运行结果(包含重复记录:苹果iPad Pro既高价又高库存?不,库存50<200,所以无重复):
-- 商品ID | 商品名称     | 价格    | 库存 | 标签
-- 2      | 华为Mate60   | 5999.00 | 80   | 高价商品
-- 3      | 苹果iPad Pro | 7999.00 | 50   | 高价商品
-- 4      | 罗技机械键盘 | 299.00  | 200  | 高库存商品(注:stock=200不满足>200)
-- 5      | 金士顿U盘   | 89.00   | 500  | 高库存商品

-- ❷ UNION(自动去重):如果有重复记录会被删除
-- 模拟场景:修改数据让某商品同时满足两个条件,再用UNION
UPDATE product SET stock = 600 WHERE product_id = 3;  -- 苹果iPad Pro库存改为600

SELECT product_id, product_name, price, stock, '高价商品' AS 标签
FROM product WHERE price > 5000
UNION  -- 去重,苹果iPad Pro只出现一次
SELECT product_id, product_name, price, stock, '高库存商品' AS 标签
FROM product WHERE stock > 200;

-- 运行结果(苹果iPad Pro只显示一条,标签为第一个查询的「高价商品」):
-- 商品ID | 商品名称     | 价格    | 库存 | 标签
-- 2      | 华为Mate60   | 5999.00 | 80   | 高价商品
-- 3      | 苹果iPad Pro | 7999.00 | 600  | 高价商品
-- 5      | 金士顿U盘   | 89.00   | 500  | 高库存商品

-- 恢复数据
UPDATE product SET stock = 50 WHERE product_id = 3;

综合案例:

mysql 复制代码
SELECT * FROM (
  -- 子查询:联合查询结果(临时表)
  SELECT
    product_id, product_name, price, stock, '高价商品' AS 标签
  FROM product WHERE price > 5000

  UNION ALL

  SELECT
    product_id, product_name, price, stock, '高库存商品' AS 标签
  FROM product WHERE stock > 200
) t  -- 给临时表起别名
ORDER BY price DESC  -- 先排序
LIMIT 0, 2;  -- 再分页:第1页,每页2条

-- 运行结果:
-- product_id | product_name   | price    | stock | 标签
-- 3          | 苹果iPad Pro   | 7999.00  | 50    | 高价商品
-- 2          | 华为Mate60     | 5999.00  | 80    | 高价商品

特点:

mysql 复制代码
1、多条查询语句的查询的列数必须是一致的
2、多条查询语句的查询的列的类型几乎相同
3、union代表去重,union all代表不去重

SQL 完整执行顺序

当一条 SQL 同时包含 WHERE/GROUP BY/HAVING/ORDER BY 时,执行顺序是固定的:

  1. FROM/JOIN:确定要查询的表和关联关系(先找到数据源)。
  2. WHERE:过滤原始数据行(分组前筛选)。
  3. GROUP BY:将过滤后的行分组聚合。
  4. HAVING:过滤分组后的统计结果(分组后筛选)。
  5. SELECT:确定要展示的字段(包括聚合函数结果、别名)。
  6. ORDER BY:对最终的统计结果行排序(最后执行)。
mysql 复制代码
SELECT
  category,
  SUM(stock) AS total_stock
FROM product
WHERE price > 100  -- 步骤2:过滤掉U盘(89)
GROUP BY category  -- 步骤3:聚合为3个分组(手机、平板、外设)
HAVING SUM(stock) > 100  -- 步骤4:过滤掉平板(50)
ORDER BY total_stock DESC;  -- 步骤6:对手机、外设排序

DML语言

插入

语法:

insert into 表名(字段名,...)

values(值1,...);

特点:

mysql 复制代码
1、字段类型和值类型一致或兼容,而且一一对应
2、可以为空的字段,可以不用插入值,或用null填充
3、不可以为空的字段,必须插入值
4、字段个数和值的个数必须一致
5、字段可以省略,但默认所有字段,并且顺序和表中的存储顺序一致

字段和值的「数量、顺序、类型」必须匹配
-- ✅ 正确写法1:指定字段,值和字段一一对应
INSERT INTO user_info (user_id, username, phone, create_time)
VALUES (4, 'zhaoliu', '13700137000', NOW());

-- ✅ 正确:字符串/日期用单引号
INSERT INTO product (product_id, product_name, price, create_time)
VALUES (6, '华为Pura70', 4499.00, '2026-01-22 10:30:00');

-- 处理特殊字符
-- 转义单引号
INSERT INTO product (product_name) VALUES ('O\'Neil的手机');  -- 方法1:\转义
使用IGNORE关键字,避免插入重复数据
-- ✅ 重复则忽略
INSERT IGNORE INTO user_info (user_id, username)
VALUES (1, 'zhangsan');  -- user_id=1已存在,不会报错,仅跳过

修改

修改单表语法:

mysql 复制代码
update 表名 set 字段=新值,字段=新值
【where 条件】

修改多表语法:

mysql 复制代码
update 表1 别名1,表2 别名2
set 字段=新值,字段=新值
where 连接条件
and 筛选条件
批量修改
-- ✅ 分批更新示例(伪代码,结合编程语言执行)
-- 第1批:更新product_id 1-1000的商品
UPDATE product
SET price = price * 0.9  -- 打9折
WHERE product_id BETWEEN 1 AND 1000;

-- 第2批:更新product_id 1001-2000的商品
UPDATE product
SET price = price * 0.9
WHERE product_id BETWEEN 1001 AND 2000;

条件更新
-- ✅ 条件更新:手机类商品降价100,平板类降价200,其他不变
UPDATE product
SET price = CASE
  WHEN category = '手机' THEN price - 100
  WHEN category = '平板' THEN price - 200
  ELSE price  -- 其他分类不更新
END
WHERE category IN ('手机', '平板');  -- 只筛选需要更新的分类

删除

方式1:delete语句

单表的删除: ★

delete from 表名 【where 筛选条件】

删除注意事项:

mysql 复制代码
核心定义:
DROP TABLE 表名 是「删除整张表」的操作,数据、表结构、索引、约束、触发器等全部删除,操作不可恢复(除非有备份),属于极高危操作。
数据 + 结构全删除(表从数据库中消失,无法再操作);
速度最快(直接删除表的元数据);
不可回滚,无任何恢复可能(除非从备份恢复);
可加 IF EXISTS 避免表不存在时报错(推荐);
需 DROP 权限,生产环境需严格管控。

-- 2. 开启事务(确保可回滚)
START TRANSACTION;
-- 3. 执行DELETE,确认无误后再提交
DELETE FROM product WHERE product_id = 6;
-- COMMIT;  -- 确认正确再提交
-- ROLLBACK;  -- 出错直接回滚(数据恢复)

多表的删除:

delete 别名1,别名2

from 表1 别名1,表2 别名2

where 连接条件

and 筛选条件;

方式2:truncate语句

mysql 复制代码
truncate table 表名
核心定义:
TRUNCATE TABLE 表名 是「清空表数据」的操作,仅删除表中所有行,表结构、索引、约束等全部保留,且操作不可回滚(非事务安全)。
只删数据,不删表结构(表还在,可继续插入数据);
速度极快(不记录单行删除日志,直接重置表);
会重置自增主键(比如主键 ID 从 1 重新开始);
无法加 WHERE 条件(只能清空全表,不能删指定行);
非事务安全(执行后无法通过 ROLLBACK 回滚);
需 DROP 权限(和 DROP 权限相同)。

两种方式的区别【面试题】

mysql 复制代码
#1.truncate不能加where条件,而delete可以加where条件
#2.truncate的效率高一丢丢
#3.truncate 删除带自增长的列的表后,如果再插入数据,数据从1开始
#delete 删除带自增长列的表后,如果再插入数据,数据从上一次的断点处开始
#4.truncate删除不能回滚,delete删除可以回滚

DDL语句

库和表的管理

库的管理:

mysql 复制代码
一、创建库
create database 库名
二、删除库
drop database 库名

表的管理:

  1. 创建表
mysql 复制代码
CREATE TABLE IF NOT EXISTS stuinfo(
	stuId INT,
	stuName VARCHAR(20),
	gender CHAR,
	bornDate DATETIME
	);
	
	DESC studentinfo;
	# 2.修改表 alter
	语法:ALTER TABLE 表名 ADD|MODIFY|DROP|CHANGE COLUMN 字段名 【字段类型】;
	
	#①修改字段名
	ALTER TABLE studentinfo CHANGE  COLUMN sex gender CHAR;
	
mysql 复制代码
#②修改表名
ALTER TABLE stuinfo RENAME [TO]  studentinfo;
#③修改字段类型和列级约束
ALTER TABLE studentinfo MODIFY COLUMN borndate DATE ;

#④添加字段

ALTER TABLE studentinfo ADD COLUMN email VARCHAR(20) first;
#⑤删除字段
ALTER TABLE studentinfo DROP COLUMN email;

删除表

DROP TABLE [IF EXISTS] studentinfo;

mysql 复制代码
-- 场景2:批量删除字段(一次性删除多个无用字段)
ALTER TABLE product
DROP COLUMN temp_tag,
DROP COLUMN unused_field;
mysql 复制代码
添加索引:
-- 场景1:给product表的product_name添加普通索引(优化按名称查询)
ALTER TABLE product
ADD INDEX idx_product_name (product_name);

-- 场景2:给user_info表的phone添加唯一索引(保证手机号不重复)
ALTER TABLE user_info
ADD UNIQUE INDEX uk_user_phone (phone);

-- 场景3:给order_item表添加联合索引(优化订单+商品的关联查询)
ALTER TABLE order_item
ADD INDEX idx_order_product (order_id, product_id);

-- 场景4:给无主键的表添加主键(如order_item表,假设item_id未设主键)
ALTER TABLE order_item
ADD PRIMARY KEY (item_id);

常见类型

mysql 复制代码
整型:
tinyint smallint int/integer bigint
无负数的场景加unsigned扩大取值范围
	
小数:
	浮点型  float(单精度浮点数约7位精度) double(双精度浮点约15位精准)
	定点型  decimal(M,D) 金额,价格
字符型: char varchar text(大文本,无需指定长度,最大长度位65535字符)  longtext(超大文本,最大4个G)
日期型:
Bool类型:bool,boolean
类型 存储空间(字节) 格式 精度 典型用途
date 3 YYYY-MM-DD 日期 生日、下单日期
time 3 HH:MM:SS 时间 配送时间、活动时段
datetime 8 YYYY-MM-DD HH:MM:SS 秒级 创建时间、更新时间
timestamp 4 YYYY-MM-DD HH:MM:SS 秒级 时间戳(自动更新)
datetime(6) 8 YYYY-MM-DD HH:MM:SS.ffffff 微秒级 精准时间(支付时间、日志)

常见约束

mysql 复制代码
NOT NULL
DEFAULT
UNIQUE
CHECK
PRIMARY KEY
FOREIGN KEY

check应用:

mysql 复制代码
CREATE TABLE product (
  product_id INT PRIMARY KEY AUTO_INCREMENT,
  product_name VARCHAR(100) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  stock INT NOT NULL,
  -- 单个字段CHECK:价格必须≥0
  CONSTRAINT chk_product_price CHECK (price >= 0),
  -- 单个字段CHECK:库存必须≥0
  CONSTRAINT chk_product_stock CHECK (stock >= 0),
  -- 多字段联合CHECK:价格>0时库存不能为0(避免「有价格无库存」)
  CONSTRAINT chk_product_price_stock CHECK (price = 0 OR stock > 0)
);

索引分类:

普通索引:

最基础的索引类型,没有任何限制,仅用于加速查询,允许索引列的值重复和为空。

唯一索引:

索引列的值必须是唯一的,但允许有空值(注意:如果是多个列的联合唯一索引,只要组合值唯一即可)。常用于保证数据唯一性,如用户手机号、邮箱。

主键索引:

特殊的唯一索引,不允许有空值,一张表只能有一个主键索引,用于唯一标识表中的每一行数据。InnoDB 引擎中,主键索引是聚簇索引的基础。

复合索引(联合索引):

适合两列同时作为where的条件场景。

遵循最左前缀法则:如果创建的是联合索引,就要遵循该法则,使用索引时,where后面的条件需要从索引的最左前列开始使用,并且不能跳过索引列中的列使用。

即使条件顺序颠倒,MySQL优化器会调整,仍生效

场景1:按照索引字段顺序使用,三个字段都使用了索引,没有问题。

场景2:直接跳过user_name使用索引字段,索引无效,未使用到索引。

场景3:不按照创建联合索引的顺序,使用索引

mysql 复制代码
-- 1. 命中索引(使用最左列age)
SELECT * FROM user WHERE age = 25;

-- 2. 命中索引(使用age+gender,完整匹配)
SELECT * FROM user WHERE age = 25 AND gender = '男';

-- 3. 命中索引(即使条件顺序颠倒,MySQL优化器会调整,仍生效)
SELECT * FROM user WHERE gender = '男' AND age = 25;

-- 4. 未命中索引(跳过左列age,仅查gender)
SELECT * FROM user WHERE gender = '男';

全文索引:

专门用于对文本内容(如文章、评论)进行全文检索,仅支持 CHAR、VARCHAR、TEXT 类型,MyISAM 和 InnoDB(5.6+)引擎支持。

查询操作在数据量比较少时,可以使用like模糊查询,但是对于大量的文本数据检索,效率很低。如果使用全文索引,查询速度会比like快很多倍。

空间索引:

用于存储地理空间数据(如点、线、面),仅支持 GEOMETRY 等空间数据类型,MyISAM 和 InnoDB(5.7+)引擎支持,且索引列不能为空。

其他维度索引划分:

数据结构划分:B+树索引,哈希索引,R树索引

物理存储划分:聚簇索引,非聚簇索引

索引数量划分:单列索引,联合索引(复合索引)

constraint foreign key references

数据库事务

只有增删改查有事务之说

特点

​ (ACID)

​ 原子性:要么都执行,要么都回滚

​ 一致性:保证数据的状态操作前和操作后保持一致

​ 隔离性:多个事务同时操作相同数据库的同一个数据时,一个事务的执行不受另外一个事务的干扰

​ 持久性:一个事务一旦提交,则数据将持久化到本地,除非其他事务对其进行修改

事务的分类:

隐式事务,没有明显的开启和结束事务的标志

mysql 复制代码
比如
insert、update、delete语句本身就是一个事务

显式事务,具有明显的开启和结束事务的标志

mysql 复制代码
	1、开启事务
	取消自动提交事务的功能
	2、编写事务的一组逻辑操作单元(多条sql语句)
	insert
	update
	delete
	3、提交事务或回滚事务

使用到的关键字

mysql 复制代码
set autocommit=0;
start transaction;
commit;
rollback;

savepoint  断点
commit to 断点
rollback to 断点

set autocommit=0
delete from account where id =25;
savepoint a; # 设置保存点
delete from account where id =28;
rollback to a;# 回滚到保存点

事务的隔离级别:

事务并发问题如何发生?

复制代码
当多个事务同时操作同一个数据库的相同数据时

事务的并发问题有哪些?

复制代码
脏读:一个事务读取到了另外一个事务未提交的数据
不可重复读:同一个事务中,多次读取到的数据不一致
幻读:一个事务读取数据时,另外一个事务进行更新,导致第一个事务读取到了没有更新的数据

如何避免事务的并发问题?

mysql 复制代码
通过设置事务的隔离级别
1、READ UNCOMMITTED
2、READ COMMITTED 可以避免脏读(oracle数据库的事务隔离级别)
3、REPEATABLE READ 可以避免脏读、不可重复读和一部分幻读(mysql的事务隔离级别)
4、SERIALIZABLE可以避免脏读、不可重复读和幻读

设置隔离级别:

mysql 复制代码
set session|global  transaction isolation level 隔离级别名;

查看隔离级别:

mysql 复制代码
select @@tx_isolation;

视图

含义:理解成一张虚拟的表

视图和表的区别:

使用方式 占用物理空间

mysql 复制代码
视图	完全相同	不占用,仅仅保存的是sql逻辑

表	完全相同	占用

视图的好处:

mysql 复制代码
1、sql语句提高重用性,效率高
2、和表实现了分离,提高了安全性

视图的创建

​ 语法:

​ CREATE VIEW 视图名

​ AS

​ 查询语句;

mysql 复制代码
create view v1 as
SELECT order_id, order_amount, order_amount / 100 AS amount_div_100
FROM order_main
ORDER BY amount_div_100;

select * from v1;

视图的增删改查

​ 1、查看视图的数据 ★

mysql 复制代码
SELECT * FROM my_v4;
SELECT * FROM my_v1 WHERE last_name='Partners';

2、插入视图的数据
INSERT INTO my_v4(last_name,department_id) VALUES('虚竹',90);

3、修改视图的数据

UPDATE my_v4 SET last_name ='梦姑' WHERE last_name='虚竹';

​ 4、删除视图的数据

​ DELETE FROM my_v4;

某些视图不能更新

​ 包含以下关键字的sql语句:分组函数、distinct、group by、having、union或者union all

​ 常量视图

​ Select中包含子查询

​ join

​ from一个不能更新的视图

​ where子句的子查询引用了from子句中的表

视图逻辑的更新

mysql 复制代码
# 方式一:
CREATE OR REPLACE VIEW test_v7
AS
SELECT last_name FROM employees
WHERE employee_id>100;
mysql 复制代码
#方式二:
ALTER VIEW test_v7
AS
SELECT employee_id FROM employees;

SELECT * FROM test_v7;

视图的删除

mysql 复制代码
DROP VIEW test_v1,test_v2,test_v3;

视图结构的查看

mysql 复制代码
DESC test_v7;
SHOW CREATE VIEW test_v7;

视图与表对比:

创建语法 是否实际占用物理空间 使用
视图 create view 只是保存了sql逻辑 增删改查,一般不能增删改
create table 保存数据 增删改查

存储过程

含义:一组经过预先编译的sql语句的集合

好处:

mysql 复制代码
1、提高了sql语句的重用性,减少了开发程序员的压力
2、提高了效率
3、减少了传输次数

分类:

mysql 复制代码
1、无返回无参
2、仅仅带in类型,无返回有参
3、仅仅带out类型,有返回无参
4、既带in又带out,有返回有参
5、带inout,有返回有参
注意:in、out、inout都可以在一个存储过程中带多个

创建存储过程

语法:

mysql 复制代码
create procedure 存储过程名(in|out|inout 参数名  参数类型,...)
begin
	存储过程体
end

类似于方法:

mysql 复制代码
修饰符 返回类型 方法名(参数类型 参数名,...){

	方法体;
}

注意

mysql 复制代码
1、需要设置新的结束标记
delimiter 新的结束标记
示例:
delimiter $

CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名  参数类型,...)
BEGIN
	sql语句1;
	sql语句2;

END $

2、存储过程体中可以有多条sql语句,如果仅仅一条sql语句,则可以省略begin end

3、参数前面的符号的意思
in:该参数只能作为输入 (该参数不能做返回值)
out:该参数只能作为输出(该参数只能做返回值)
inout:既能做输入又能做输出

调用存储过程

​ call 存储过程名(实参列表)

函数

创建函数

学过的函数:LENGTH、SUBSTR、CONCAT等

语法:

mysql 复制代码
CREATE FUNCTION 函数名(参数名 参数类型,...) RETURNS 返回类型
BEGIN
	函数体
END

调用函数

​ SELECT 函数名(实参列表)

函数和存储过程的区别

mysql 复制代码
		关键字		调用语法	返回值			应用场景
函数		FUNCTION	SELECT 函数()	只能是一个		一般用于查询结果为一个值并返回时,当有返回值而且仅仅一个
存储过程	PROCEDURE	CALL 存储过程()	可以有0个或多个		一般用于更新

流程控制结构

系统变量

一、全局变量

作用域:针对于所有会话(连接)有效,但不能跨重启

mysql 复制代码
查看所有全局变量
SHOW GLOBAL VARIABLES;
查看满足条件的部分系统变量
SHOW GLOBAL VARIABLES LIKE '%char%';
查看指定的系统变量的值
SELECT @@global.autocommit;
为某个系统变量赋值
SET @@global.autocommit=0;
SET GLOBAL autocommit=0;

二、会话变量

作用域:针对于当前会话(连接)有效

mysql 复制代码
查看所有会话变量
SHOW SESSION VARIABLES;
查看满足条件的部分会话变量
SHOW SESSION VARIABLES LIKE '%char%';
查看指定的会话变量的值
SELECT @@autocommit;
SELECT @@session.tx_isolation;
为某个会话变量赋值
SET @@session.tx_isolation='read-uncommitted';
SET SESSION tx_isolation='read-committed';

自定义变量

一、用户变量

声明并初始化:

mysql 复制代码
SET @变量名=值;
SET @变量名:=值;
SELECT @变量名:=值;

赋值:

mysql 复制代码
方式一:一般用于赋简单的值
SET 变量名=值;
SET 变量名:=值;
SELECT 变量名:=值;
mysql 复制代码
方式二:一般用于赋表 中的字段值
SELECT 字段名或表达式 INTO 变量
FROM 表;

使用:

mysql 复制代码
select @变量名;

二、局部变量

声明:

复制代码
declare 变量名 类型 【default 值】;

赋值:

mysql 复制代码
方式一:一般用于赋简单的值
SET 变量名=值;
SET 变量名:=值;
SELECT 变量名:=值;
mysql 复制代码
方式二:一般用于赋表中的字段值
SELECT 字段名或表达式 INTO 变量
FROM 表;

使用:

mysql 复制代码
select 变量名

二者的区别:

mysql 复制代码
		作用域			定义位置		         语法
		用户变量	    当前会话的任何地方		 加@符号,不用指定类型
         局部变量	     定义它的BEGIN END中 	  BEGIN END的第一句话	一般不用加@,需要指定类型

分支

一、if函数

语法:if(条件,值1,值2)

特点:可以用在任何位置

二、case语句

语法:

mysql 复制代码
情况一:类似于switch
case 表达式
when 值1 then 结果1或语句1(如果是语句,需要加分号) 
when 值2 then 结果2或语句2(如果是语句,需要加分号)
...
else 结果n或语句n(如果是语句,需要加分号)
end 【case】(如果是放在begin end中需要加上case,如果放在select后面不需要)

情况二:类似于多重if
case 
when 条件1 then 结果1或语句1(如果是语句,需要加分号) 
when 条件2 then 结果2或语句2(如果是语句,需要加分号)
...
else 结果n或语句n(如果是语句,需要加分号)
end 【case】(如果是放在begin end中需要加上case,如果放在select后面不需要)

特点:

可以用在任何位置

三、if elseif语句

语法:

mysql 复制代码
if 情况1 then 语句1;
elseif 情况2 then 语句2;
...
else 语句n;
end if;

特点:

只能用在begin end中!!!!!!!!!!!!!!!

三者比较: 应用场合

if函数 简单双分支

case结构 等值判断 的多分支

if结构 区间判断 的多分支

循环

语法:

mysql 复制代码
【标签:】WHILE 循环条件  DO
	循环体
END WHILE 【标签】;

特点:

mysql 复制代码
只能放在BEGIN END里面
如果要搭配leave跳转语句,需要使用标签,否则可以不用标签
leave类似于java中的break语句,跳出所在循环!!!
相关推荐
无限码力8 小时前
华为OD技术面真题 - 数据库MySQL - 3
数据库·mysql·华为od·八股文·华为od技术面八股文
heartbeat..8 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
Prince-Peng8 小时前
技术架构系列 - 详解Redis
数据结构·数据库·redis·分布式·缓存·中间件·架构
虾说羊8 小时前
redis中的哨兵机制
数据库·redis·缓存
_F_y8 小时前
MySQL视图
数据库·mysql
2301_790300968 小时前
Python单元测试(unittest)实战指南
jvm·数据库·python
九章-9 小时前
一库平替,融合致胜:国产数据库的“统型”范式革命
数据库·融合数据库
2401_838472519 小时前
使用Scikit-learn构建你的第一个机器学习模型
jvm·数据库·python
u0109272719 小时前
使用Python进行网络设备自动配置
jvm·数据库·python
wengqidaifeng9 小时前
数据结构---顺序表的奥秘(下)
c语言·数据结构·数据库