oracle 23c的pl/sql新特性中,for update skip locked可一条语句安全获取未被锁定行,json_object(*)自动构json,member of简化集合判断,但均需匹配场景慎用。

Oracle 23c 的 PL/SQL 新特性确实能减少样板代码,但多数只在特定场景下真正省事——盲目套用反而增加理解成本。
用 FOR UPDATE SKIP LOCKED 替代手写轮询逻辑
以前处理任务队列常要加锁、查、更新、提交四步,还容易死锁或漏任务。23c 支持在 SELECT ... FOR UPDATE 中直接加 SKIP LOCKED,一条语句就能安全取走未被其他会话锁定的行。
- 仅适用于
UPDATE或DELETE前的查询,不能用于纯只读场景 - 必须配合
FOR UPDATE使用,单独写SKIP LOCKED会报ORA-02014 - 示例:
DECLARE l_id NUMBER; BEGIN SELECT id INTO l_id FROM task_queue WHERE status = 'PENDING' FOR UPDATE SKIP LOCKED FETCH FIRST 1 ROW ONLY; UPDATE task_queue SET status = 'PROCESSING' WHERE id = l_id; END;
用 JSON_OBJECT(*) 快速构造动态 JSON
以前拼 JSON 要手动拼键名、处理 NULL、转义字符串,极易出错。23c 允许对任意查询结果直接用 JSON_OBJECT(*) 生成结构化 JSON,字段名自动作为 key,NULL 默认忽略(可配 NULL ON NULL)。
- 不支持嵌套对象或数组,复杂结构仍需
JSON_ARRAYAGG配合 - 若查询含重复列名(如多表 JOIN),会报
ORA-40578,必须显式别名 - 性能比手拼快约 3–5 倍,但大量数据时仍建议分页生成,避免 PGA 溢出
用 MEMBER OF 简化集合判断(注意类型约束)
判断某值是否在嵌套表中,以前得写循环或 EXISTS (SELECT ...)。23c 支持标准 SQL 的 MEMBER OF 语法,更直观。
- 只接受已声明的嵌套表变量(
TYPE t IS TABLE OF ...),不能直接用字面量数组 - 比较时严格区分大小写和空格,
'abc'和'abc '判定为不同 - 底层仍走全扫描,大数据量时不如建临时表 + 索引
- 示例:
DECLARE TYPE str_list IS TABLE OF VARCHAR2(10); v_list str_list := str_list('A', 'B', 'C'); BEGIN IF 'B' MEMBER OF v_list THEN DBMS_OUTPUT.PUT_LINE('found'); END IF; END;
这些特性不是“越新越好”,比如 JSON_OBJECT(*) 在需要精确控制字段顺序或默认值时,反而不如传统拼接清晰;SKIP LOCKED 在高并发短事务下效果明显,但长事务可能让其他会话长时间等不到锁。关键还是看你的数据模式和并发模型,而不是版本号。











