目录
一、MySQL 常用函数
1. 字符串函数
1.1 基本字符串操作
1.2 字符串截取与处理
1.3 字符串搜索与替换
2. 数值函数
2.1 基本数学运算
2.2 数学计算
2.3 随机数与符号
3. 日期时间函数
3.1 获取当前时间
3.2 日期时间计算
3.3 日期时间提取
3.4 日期时间格式化
4. 条件函数
4.1 流程控制函数
4.2 聚合函数
5. 窗口函数 (MySQL 8.0+)
6. JSON 函数 (MySQL 5.7+)
7. 系统信息函数
8. 加密函数
二、MySQL 约束
1. 主键约束 (PRIMARY KEY)
1.1 基本用法
1.2 修改表添加主键
1.3 自增主键
2. 外键约束 (FOREIGN KEY)
2.1 基本用法
2.2 级联操作
2.3 修改表添加外键
3. 唯一约束 (UNIQUE)
3.1 基本用法
3.2 多列组合唯一
3.3 修改表添加唯一约束
4. 非空约束 (NOT NULL)
4.1 基本用法
4.2 修改表添加非空约束
5. 默认值约束 (DEFAULT)
5.1 基本用法
5.2 修改表添加默认值
6. 检查约束 (CHECK)
6.1 基本用法
6.2 命名检查约束
6.3 修改表添加检查约束
7. 约束管理
7.1 查看约束
7.2 删除约束
三、多表查询
1. 内连接 (INNER JOIN)
2. 左外连接 (LEFT JOIN)
3. 右外连接 (RIGHT JOIN)
4. 全外连接 (FULL OUTER JOIN) - MySQL不支持,可用UNION模拟
5. 交叉连接 (CROSS JOIN)
6. 自连接 (SELF JOIN)
7. 自然连接 (NATURAL JOIN)
8. USING 子句
9. 子查询
9.1 WHERE子句中的子查询
(1)标量子查询(返回单个值)
(2)列子查询(返回单列多行)
(3)行子查询(返回单行多列)
9.2 FROM子句中的子查询(派生表)
9.3 SELECT子句中的子查询(标量子查询)
9.4 HAVING子句中的子查询
9.5 EXISTS和NOT EXISTS子查询
10. 集合操作
10.1 UNION 和 UNION ALL
10.2 INTERSECT (MySQL 8.0.31+)
10.3 EXCEPT/MINUS (MySQL 8.0.31+)
四、事务 (Transaction)
1. 事务的基本特性 (ACID)
2. 事务控制语句
3. 事务隔离级别
4. 事务并发问题
(1)脏读 (Dirty Read)
(2)不可重复读 (Non-repeatable Read)
(3)幻读 (Phantom Read)
5. 保存点 (SAVEPOINT)
一、MySQL 常用函数
MySQL 提供了丰富的内置函数,可以用于数据处理、计算和转换。这些函数主要分为以下几类:
1. 字符串函数
1.1 基本字符串操作
-- 连接字符串SELECT CONCAT('Hello', ' ', 'World'); -- 输出: Hello WorldSELECT CONCAT_WS('-', '2023', '01', '01'); -- 用分隔符连接: 2023-01-01-- 字符串长度SELECT LENGTH('MySQL'); -- 字节数: 5SELECT CHAR_LENGTH('MySQL'); -- 字符数: 5-- 大小写转换SELECT UPPER('mysql'); -- MYSQLSELECT LOWER('MySQL'); -- mysql
1.2 字符串截取与处理
-- 截取字符串SELECT SUBSTRING('MySQL', 2, 3); -- ySQ (从第2个字符开始,取3个)SELECT LEFT('MySQL', 2); -- MySELECT RIGHT('MySQL', 3); -- SQL-- 去除空格SELECT TRIM(' MySQL '); -- 'MySQL'SELECT LTRIM(' MySQL'); -- 'MySQL'SELECT RTRIM('MySQL '); -- 'MySQL'-- 填充字符串SELECT LPAD('5', 3, '0'); -- 005SELECT RPAD('Hi', 5, '!'); -- Hi!!!
1.3 字符串搜索与替换
-- 查找位置SELECT INSTR('MySQL', 'SQL'); -- 3 (SQL在MySQL中的位置)SELECT LOCATE('SQL', 'MySQL'); -- 3-- 替换字符串SELECT REPLACE('MySQL', 'SQL', 'Database'); -- MyDatabase-- 正则表达式SELECT 'MySQL' REGEXP '^My'; -- 1 (匹配成功)SELECT REGEXP_REPLACE('abc123', '[0-9]', 'X'); -- abcXXX
2. 数值函数
2.1 基本数学运算
-- 四舍五入SELECT ROUND(3.14159, 2); -- 3.14SELECT ROUND(123.456, -1); -- 120 (小数点左侧舍入)-- 取整SELECT CEIL(3.14); -- 4 (向上取整)SELECT FLOOR(3.14); -- 3 (向下取整)SELECT TRUNCATE(3.14159, 2); -- 3.14 (截断)-- 绝对值SELECT ABS(-10); -- 10
2.2 数学计算
-- 幂运算SELECT POWER(2, 3); -- 8 (2的3次方)SELECT SQRT(16); -- 4 (平方根)-- 对数SELECT LOG(2, 8); -- 3 (以2为底8的对数)SELECT LN(10); -- 自然对数SELECT LOG10(100); -- 2-- 三角函数SELECT SIN(PI()/2); -- 1SELECT COS(0); -- 1SELECT TAN(PI()/4); -- 约等于1
2.3 随机数与符号
-- 随机数SELECT RAND(); -- 0到1之间的随机数SELECT FLOOR(1 + RAND() * 10); -- 1-10的随机整数-- 符号判断SELECT SIGN(-10); -- -1SELECT SIGN(0); -- 0SELECT SIGN(10); -- 1
3. 日期时间函数
3.1 获取当前时间
SELECT NOW(); -- 当前日期和时间 (2023-01-01 12:34:56)SELECT CURDATE(); -- 当前日期 (2023-01-01)SELECT CURTIME(); -- 当前时间 (12:34:56)SELECT UNIX_TIMESTAMP(); -- 当前UNIX时间戳
3.2 日期时间计算
-- 日期加减SELECT DATE_ADD(NOW(), INTERVAL 1 DAY); -- 加1天SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH); -- 减1个月SELECT NOW() + INTERVAL 1 HOUR; -- 加1小时-- 日期差SELECT DATEDIFF('2023-12-31', '2023-01-01'); -- 364 (天数差)SELECT TIMESTAMPDIFF(MONTH, '2023-01-01', '2023-12-31'); -- 11 (月数差)
3.3 日期时间提取
-- 提取日期部分SELECT YEAR(NOW()); -- 2023SELECT MONTH(NOW()); -- 1-12SELECT DAY(NOW()); -- 1-31SELECT HOUR(NOW()); -- 0-23SELECT MINUTE(NOW()); -- 0-59SELECT SECOND(NOW()); -- 0-59-- 星期和季度SELECT DAYNAME(NOW()); -- MondaySELECT DAYOFWEEK(NOW()); -- 1=周日, 2=周一,...,7=周六SELECT QUARTER(NOW()); -- 1-4
3.4 日期时间格式化
-- 格式化日期SELECT DATE_FORMAT(NOW(), '%Y-%m-%d'); -- 2023-01-01SELECT DATE_FORMAT(NOW(), '%H:%i:%s'); -- 12:34:56SELECT DATE_FORMAT(NOW(), '%W, %M %e, %Y'); -- Sunday, January 1, 2023-- 解析日期字符串SELECT STR_TO_DATE('01-01-2023', '%d-%m-%Y'); -- 2023-01-01
4. 条件函数
4.1 流程控制函数
-- IF函数SELECT IF(1 > 0, 'True', 'False'); -- TrueSELECT IFNULL(NULL, 'Default'); -- DefaultSELECT NULLIF(10, 10); -- NULL (两值相等返回NULL)-- CASE WHENSELECT score,CASE WHEN score >= 90 THEN 'A'WHEN score >= 80 THEN 'B'WHEN score >= 70 THEN 'C'ELSE 'D'END AS gradeFROM students;
4.2 聚合函数
-- 基本聚合SELECT COUNT(*) FROM users; -- 记录数SELECT AVG(price) FROM products; -- 平均值SELECT SUM(quantity) FROM order_items; -- 总和SELECT MAX(salary) FROM employees; -- 最大值SELECT MIN(age) FROM customers; -- 最小值-- 分组聚合SELECT department_id, AVG(salary)FROM employeesGROUP BY department_idHAVING AVG(salary) > 5000;
5. 窗口函数 (MySQL 8.0+)
-- 排名函数SELECT name, salary,RANK() OVER (ORDER BY salary DESC) AS rank,DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank,ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_numFROM employees;-- 分区计算SELECT department_id, name, salary,AVG(salary) OVER (PARTITION BY department_id) AS dept_avg_salaryFROM employees;-- 累计计算SELECT order_date, amount,SUM(amount) OVER (ORDER BY order_date) AS running_totalFROM orders;
6. JSON 函数 (MySQL 5.7+)
-- 创建JSONSELECT JSON_OBJECT('name', 'John', 'age', 30);SELECT JSON_ARRAY(1, 'a', TRUE, NULL);-- 提取JSON值SELECT JSON_EXTRACT('{"name": "John", "age": 30}', '$.name'); -- "John"SELECT JSON_UNQUOTE(JSON_EXTRACT('{"name": "John"}', '$.name')); -- John-- 修改JSONSELECT JSON_SET('{"name": "John"}', '$.age', 30); -- {"name": "John", "age": 30}SELECT JSON_REMOVE('{"name": "John", "age": 30}', '$.age'); -- {"name": "John"}
7. 系统信息函数
-- 数据库信息SELECT DATABASE(); -- 当前数据库名SELECT USER(); -- 当前用户SELECT VERSION(); -- MySQL版本-- 连接信息SELECT CONNECTION_ID(); -- 连接IDSELECT LAST_INSERT_ID(); -- 最后插入的ID-- 性能分析SELECT BENCHMARK(1000000, MD5('test')); -- 执行MD5 100万次
8. 加密函数
-- 哈希函数SELECT MD5('password'); -- 32字符MD5哈希SELECT SHA1('password'); -- 40字符SHA1哈希SELECT SHA2('password', 256); -- 64字符SHA256哈希-- 加密解密SELECT AES_ENCRYPT('secret', 'key');SELECT AES_DECRYPT(encrypted_data, 'key');-- 密码函数SELECT PASSWORD('mypass'); -- 已废弃,不推荐使用
二、MySQL 约束
约束是用于限制表中数据类型的规则,确保数据的准确性和可靠性。MySQL 支持多种约束类型,以下是简要介绍:
1. 主键约束 (PRIMARY KEY)
1.1 基本用法
-- 创建表时定义单列主键CREATE TABLE users (user_id INT PRIMARY KEY,username VARCHAR(50) NOT NULL);-- 创建表时定义多列组合主键CREATE TABLE order_items (order_id INT,product_id INT,quantity INT,PRIMARY KEY (order_id, product_id));
1.2 修改表添加主键
ALTER TABLE employees ADD PRIMARY KEY (emp_id);
1.3 自增主键
CREATE TABLE products (product_id INT AUTO_INCREMENT PRIMARY KEY,product_name VARCHAR(100) NOT NULL);
2. 外键约束 (FOREIGN KEY)
2.1 基本用法
CREATE TABLE orders (order_id INT PRIMARY KEY,customer_id INT,order_date DATE,FOREIGN KEY (customer_id) REFERENCES customers(customer_id));
2.2 级联操作
CREATE TABLE order_items (item_id INT PRIMARY KEY,order_id INT,product_id INT,FOREIGN KEY (order_id) REFERENCES orders(order_id)ON DELETE CASCADE -- 主表删除时级联删除ON UPDATE CASCADE, -- 主表更新时级联更新FOREIGN KEY (product_id) REFERENCES products(product_id)ON DELETE SET NULL -- 主表删除时设为NULL);
2.3 修改表添加外键
ALTER TABLE employeesADD CONSTRAINT fk_deptFOREIGN KEY (department_id) REFERENCES departments(dept_id);
3. 唯一约束 (UNIQUE)
3.1 基本用法
CREATE TABLE employees (emp_id INT PRIMARY KEY,email VARCHAR(100) UNIQUE,phone VARCHAR(20),CONSTRAINT uc_phone UNIQUE (phone) -- 命名约束);
3.2 多列组合唯一
CREATE TABLE class_registry (student_id INT,class_id INT,semester VARCHAR(10),UNIQUE (student_id, class_id, semester));
3.3 修改表添加唯一约束
ALTER TABLE products ADD UNIQUE (product_code);
4. 非空约束 (NOT NULL)
4.1 基本用法
CREATE TABLE customers (customer_id INT PRIMARY KEY,name VARCHAR(100) NOT NULL,email VARCHAR(100) NOT NULL UNIQUE);
4.2 修改表添加非空约束
ALTER TABLE employees MODIFY COLUMN hire_date DATE NOT NULL;
5. 默认值约束 (DEFAULT)
5.1 基本用法
CREATE TABLE orders (order_id INT PRIMARY KEY,order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,status VARCHAR(20) DEFAULT 'Pending',total_amount DECIMAL(10,2) DEFAULT 0.00);
5.2 修改表添加默认值
ALTER TABLE products ALTER COLUMN stock SET DEFAULT 0;
6. 检查约束 (CHECK)
6.1 基本用法
CREATE TABLE employees (emp_id INT PRIMARY KEY,name VARCHAR(100) NOT NULL,salary DECIMAL(10,2) CHECK (salary > 0),age INT CHECK (age >= 18 AND age <= 65),gender VARCHAR(10) CHECK (gender IN ('Male', 'Female', 'Other')));
6.2 命名检查约束
CREATE TABLE products (product_id INT PRIMARY KEY,price DECIMAL(10,2),discount DECIMAL(10,2),CONSTRAINT chk_price CHECK (price > 0),CONSTRAINT chk_discount CHECK (discount >= 0 AND discount <= price));
6.3 修改表添加检查约束
ALTER TABLE employeesADD CONSTRAINT chk_salary CHECK (salary > 0);
7. 约束管理
7.1 查看约束
-- 查看表的所有约束SELECT * FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = 'your_database' AND TABLE_NAME = 'your_table';-- 查看外键约束SELECT * FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = 'your_database';
7.2 删除约束
-- 删除主键ALTER TABLE users DROP PRIMARY KEY;-- 删除外键ALTER TABLE orders DROP FOREIGN KEY fk_customer;-- 删除唯一约束ALTER TABLE employees DROP INDEX uc_phone;-- 删除检查约束 (MySQL 8.0.16+)ALTER TABLE employees DROP CHECK chk_salary;
三、多表查询
1. 内连接 (INNER JOIN)
-- 基本内连接SELECT e.emp_id, e.emp_name, d.dept_nameFROM employees eINNER JOIN departments d ON e.dept_id = d.dept_id;-- 多表内连接SELECT o.order_id,c.customer_name,p.product_name,oi.quantityFROM orders oINNER JOIN customers c ON o.customer_id = c.customer_idINNER JOIN order_items oi ON o.order_id = oi.order_idINNER JOIN products p ON oi.product_id = p.product_id;
2. 左外连接 (LEFT JOIN)
-- 保留左表所有记录SELECT d.dept_name,e.emp_nameFROM departments dLEFT JOIN employees e ON d.dept_id = e.dept_id;
3. 右外连接 (RIGHT JOIN)
-- 保留右表所有记录SELECT e.emp_name,d.dept_nameFROM employees eRIGHT JOIN departments d ON e.dept_id = d.dept_id;
4. 全外连接 (FULL OUTER JOIN) - MySQL不支持,可用UNION模拟
-- 使用UNION模拟全连接SELECT e.emp_name,d.dept_nameFROM employees eLEFT JOIN departments d ON e.dept_id = d.dept_idUNIONSELECT e.emp_name,d.dept_nameFROM employees eRIGHT JOIN departments d ON e.dept_id = d.dept_idWHERE e.dept_id IS NULL;
5. 交叉连接 (CROSS JOIN)
-- 笛卡尔积SELECT e.emp_name,p.project_nameFROM employees eCROSS JOIN projects p;
6. 自连接 (SELF JOIN)
-- 查找员工及其经理SELECT e1.emp_name AS employee,e2.emp_name AS managerFROM employees e1LEFT JOIN employees e2 ON e1.manager_id = e2.emp_id;-- 查找同一部门的员工对SELECT a.emp_name AS employee1,b.emp_name AS employee2,a.dept_idFROM employees aJOIN employees b ON a.dept_id = b.dept_idWHERE a.emp_id < b.emp_id;
7. 自然连接 (NATURAL JOIN)
-- 自动匹配相同名称的列SELECT e.emp_name,d.dept_nameFROM employees eNATURAL JOIN departments d;
8. USING 子句
-- 简化连接条件SELECT e.emp_name,d.dept_nameFROM employees eJOIN departments d USING (dept_id);
9. 子查询
9.1 WHERE子句中的子查询
(1)标量子查询(返回单个值)
-- 查询高于平均工资的员工SELECT emp_name, salaryFROM employeesWHERE salary > (SELECT AVG(salary) FROM employees);-- 查询最后入职的员工SELECT emp_name, hire_dateFROM employeesWHERE hire_date = (SELECT MAX(hire_date) FROM employees);
(2)列子查询(返回单列多行)
-- 使用IN操作符SELECT emp_name, dept_idFROM employeesWHERE dept_id IN (SELECT dept_id FROM departments WHERE location = 'New York');-- 使用ANY/SOME操作符SELECT emp_name, salaryFROM employeesWHERE salary > ANY (SELECT salary FROM employees WHERE dept_id = 10);-- 使用ALL操作符SELECT emp_name, salaryFROM employeesWHERE salary > ALL (SELECT salary FROM employees WHERE dept_id = 10);
(3)行子查询(返回单行多列)
-- 查询与特定员工工资和部门相同的其他员工SELECT emp_name, salary, dept_idFROM employeesWHERE (salary, dept_id) = (SELECT salary, dept_id FROM employees WHERE emp_id = 100);
9.2 FROM子句中的子查询(派生表)
-- 计算每个部门的平均工资,然后查询高于公司平均工资的部门SELECT d.dept_name, dept_avg.avg_salaryFROM departments dJOIN (SELECT dept_id, AVG(salary) AS avg_salaryFROM employeesGROUP BY dept_id) dept_avg ON d.dept_id = dept_avg.dept_idWHERE dept_avg.avg_salary > (SELECT AVG(salary) FROM employees);-- 使用派生表进行分页SELECT *FROM (SELECT emp_id, emp_name, salaryFROM employeesORDER BY salary DESCLIMIT 10) AS top_earners;
9.3 SELECT子句中的子查询(标量子查询)
-- 查询员工信息及其部门平均工资SELECT emp_id,emp_name,salary,(SELECT AVG(salary) FROM employees e2 WHERE e2.dept_id = e1.dept_id) AS dept_avg_salary,salary - (SELECT AVG(salary) FROM employees e2 WHERE e2.dept_id = e1.dept_id) AS diff_from_avgFROM employees e1;-- 查询产品信息及订单数量SELECT p.product_id,p.product_name,(SELECT COUNT(*) FROM order_items oi WHERE oi.product_id = p.product_id) AS order_countFROM products p;
9.4 HAVING子句中的子查询
-- 查询平均工资高于公司平均工资的部门SELECT dept_id, AVG(salary) AS avg_salaryFROM employeesGROUP BY dept_idHAVING AVG(salary) > (SELECT AVG(salary) FROM employees);-- 查询订单数量超过客户平均订单数的客户SELECT customer_id, COUNT(*) AS order_countFROM ordersGROUP BY customer_idHAVING COUNT(*) > (SELECT AVG(order_count) FROM (SELECT COUNT(*) AS order_count FROM orders GROUP BY customer_id) AS counts);
9.5 EXISTS和NOT EXISTS子查询
-- 查询有订单的客户SELECT customer_nameFROM customers cWHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id);-- 查询没有订单的客户SELECT customer_nameFROM customers cWHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id);-- 查询购买了所有产品的客户SELECT customer_nameFROM customers cWHERE NOT EXISTS (SELECT product_idFROM products pWHERE NOT EXISTS (SELECT 1FROM orders oJOIN order_items oi ON o.order_id = oi.order_idWHERE o.customer_id = c.customer_idAND oi.product_id = p.product_id));
10. 集合操作
10.1 UNION 和 UNION ALL
-- 合并结果集 (去重)SELECT product_id FROM current_productsUNIONSELECT product_id FROM discontinued_products;-- 合并结果集 (保留重复)SELECT product_id FROM current_productsUNION ALLSELECT product_id FROM discontinued_products;
10.2 INTERSECT (MySQL 8.0.31+)
-- 交集SELECT customer_id FROM premium_customersINTERSECTSELECT customer_id FROM active_customers;
10.3 EXCEPT/MINUS (MySQL 8.0.31+)
-- 差集SELECT employee_id FROM all_employeesEXCEPTSELECT employee_id FROM current_employees;
四、事务 (Transaction)
1. 事务的基本特性 (ACID)
-
原子性 (Atomicity): 事务是不可分割的工作单位。
-
一致性 (Consistency): 事务执行前后数据库保持一致状态。
-
隔离性 (Isolation): 多个事务并发执行时互不干扰。
-
持久性 (Durability): 事务提交后对数据库的改变是永久的。
2. 事务控制语句
-- 开始事务START TRANSACTION;-- 执行SQL语句INSERT INTO accounts (user_id, balance) VALUES (1, 1000);UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;-- 提交事务COMMIT;-- 回滚事务ROLLBACK;
3. 事务隔离级别
-- 查看当前隔离级别SELECT @@transaction_isolation;-- 设置隔离级别(会话级)SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;-- 设置隔离级别(全局)SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;-- 四种隔离级别SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;SET TRANSACTION ISOLATION LEVEL READ COMMITTED;SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; -- MySQL默认SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
四种隔离级别比较:
隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
---|---|---|---|---|
READ UNCOMMITTED | 可能 | 可能 | 可能 | 最高 |
READ COMMITTED | 不可能 | 可能 | 可能 | 高 |
REPEATABLE READ(默认) | 不可能 | 不可能 | 可能 | 中 |
SERIALIZABLE | 不可能 | 不可能 | 不可能 | 低 |
4. 事务并发问题
(1)脏读 (Dirty Read)
读取到其他事务未提交的数据。
-- 事务ASET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;START TRANSACTION;SELECT * FROM accounts WHERE user_id = 1; -- 可能读取到事务B未提交的数据-- 事务BSTART TRANSACTION;UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;-- 尚未提交
(2)不可重复读 (Non-repeatable Read)
同一事务内多次读取同一数据结果不同。
-- 事务ASET TRANSACTION ISOLATION LEVEL READ COMMITTED;START TRANSACTION;SELECT * FROM accounts WHERE user_id = 1; -- 第一次读取-- 事务B提交了更新UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;COMMIT;SELECT * FROM accounts WHERE user_id = 1; -- 第二次读取结果不同
(3)幻读 (Phantom Read)
同一事务内多次查询返回的结果集不同。
-- 事务ASET TRANSACTION ISOLATION LEVEL REPEATABLE READ;START TRANSACTION;SELECT * FROM accounts WHERE balance > 1000; -- 返回10条记录-- 事务B插入新记录并提交INSERT INTO accounts VALUES (11, '新用户', 1500);COMMIT;SELECT * FROM accounts WHERE balance > 1000; -- 返回11条记录
5. 保存点 (SAVEPOINT)
START TRANSACTION;INSERT INTO orders (order_id, user_id) VALUES (1, 1);SAVEPOINT savepoint1;UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;-- 如果出现问题可以回滚到保存点ROLLBACK TO savepoint1;COMMIT;