Zzzxb's Blog

你要静心学习那份等待时机的成熟的情绪,也要你一定保有这份等待之外的努力和坚持。

MySQL 笔记 Feb 25, 2025

JSON

  1. JSON文档元素可以被快速访问
  2. 服务器再次读取JSON文档时夫需要重新解析文本
  3. 可以直接通过文档元素作为条件,而不需要查询整个文档
# 创建表
create table detail (
    id INT primary key auto_increment,
    name VARCHAR(16) not null,
    other JSON
)

# 添加数据
insert detail(name, other) values('Zzzxb', '{
  "age": "18",
  "gender": "man",
  "hobby": [
    "programme",
    "game"
  ],
  "from": {
    "country": "China",
    "province": "BeiJing"
  }
}');

# 查询数据 - 查询来自JSON内部字段
select other->>'$.from' from detail;
# 查询数据 - 格式美化
select JSON_PRETTY(other) from detail;
select JSON_PRETTY(other->>'$.from') from detail;

JSON FUNCTION

延申阅读

公用表达式(CTE)

使用CTE后,子查询只会计算一次,而使用派生类,查询会根据派生表的引用次数 进行多次查询

  1. 查询结果可以多次复用, 多次操作同一张表时可以通过CTE复用
  2. 分为非递归和递归

非递归

# 示例只是展示使用方式,并不没有展示具体场景
# 派生表(子查询)
select d.name, ed.details from
(select * from detail) as d, emp_details as ed
where d.name = ed.details->>'$.name';

# 单个cte
with nickname as (select * from detail)
select nk1.name, nk2.other from
             nickname as nk1,
             nickname as nk2
where nk1.name = nk2.name;

# 多个cte
with nickname1 as (select * from detail),
     nickname2 as (select * from emp_details)
select nk1.name, nk2.details from
             nickname1 as nk1,
             nickname2 as nk2
where nk1.name = nk2.details->>'$.name';

递归

递归CTE是一种特殊的CTE, 其子查询会引用自己的名字。 WITH 子句必须以 WITH RECURSIVE 开头。 递归CTE子查询包裹两部分: seed 查询和 recursive 查询, 由 UNION [ALL]UNION DISTINCT 分隔。

# 格式
WITH RECURSIVE cte as
(select * from table_name) /* seed select*/
union all
(select * from cte, table_name) /* recursive select */
select * from cte;

# 打印从15的所有数字
WITH RECURSIVE cte (n) as
(select 1
 union all
 select n + 1 from cte where n < 5
)
select * from cte;

生成列

create table employees (
    id int not null primary key,
    first_name VARCHAR(8) not null,
    last_name VARCHAR(16) not null,
    hire_date date not null,
    full_name VARCHAR(24) as (CONCAT(first_name, last_name)),
    key name (first_name, last_name)
)

insert employees (id, first_name, last_name, hire_date)
values (1, 'Zzz', 'xb', NOW());

alter table employees add hire_date_year year as (YEAR(hire_date)) virtual;

延申阅读

窗口函数

对于查询中的每一行,可以使用窗口函数,利用与该行相关的执行计算。使用OVERWINDOW 子句完成.

延申阅读 窗口函数行号方法ROW_NUMBER

事务

执行事务

-- BEGIN 或 START TRANSACTION 开启事务 
BEGIN

-- 要执行的 SQL 语句

-- COMMIT 提交事务, ROLLBACK 回滚事务
COMMIT

延申阅读

保存点

BEGIN

-- 需要执行的 SQL

SAVEPOINT flag_name; # 这里是保存点

-- 需要执行的 SQL

ROLLBACK TO flag_name; # 这里是回滚点

隔离级别

-- 加锁
LOCK TABLE table_name [READ | WRITE]
-- 释放锁
UNLOCK TABLE;

-- 冻结对数据库所有的写入操作 
FLUSH TABLES WITH READ LOCK;

除共享锁(一个表可以有多个共享锁)之外,没有两个锁可以一起加在一个表上。如果一个表已经有一个共享锁,此时有一个排他锁进来, 那么它将被保留在队列中,知道共享锁释放。

元数据锁