第 3 站练习答案
键集分页
sql
SELECT order_id, status, total_amount, created_at
FROM sales_order
WHERE (created_at, order_id) < ('2026-01-01 00:00:00.000000', 100)
ORDER BY created_at DESC, order_id DESC
LIMIT 20;复合比较的列顺序必须与排序一致。
NULL 安全反连接
sql
SELECT c.customer_id
FROM customer AS c
WHERE NOT EXISTS (
SELECT 1 FROM sales_order AS o
WHERE o.customer_id = c.customer_id
);NOT EXISTS 以相关条件判断是否存在,不会被子查询结果中的 NULL 污染。
乐观更新
sql
UPDATE sales_order
SET status = 'cancelled', version_no = version_no + 1
WHERE order_id = 1
AND status = 'paid'
AND version_no = 1;调用方必须检查受影响行数;零行意味着状态或版本不再满足前置条件。
加码题解:安全写入与分页
sql
UPDATE orders
SET status = 'CANCELLED'
WHERE id = 42 AND status = 'PENDING';
SELECT ROW_COUNT();关键推理
条件写入把并发状态判断交给数据库,ROW_COUNT 是调用方的事实依据。
可替代方案
大表列表使用 created_at + id 的 keyset cursor。
典型错误
无 WHERE 更新、按非唯一时间字段 offset 分页、忽略警告和自动提交。
复盘时请附上版本、隔离级别、执行计划或恢复位置中的相关证据;没有证据的“看起来正确”不算完成。