26ai新特性实战:JSON关系二元性验证指令
胖头鱼的技术专栏-447 26ai新特性实战:JSON关系二元性验证指令(20260716)
作者:胖头鱼的鱼缸(尹海文)
Oracle ACE Pro: Database
PostgreSQL ACE10年+数据库行业经验
拥有OCM 11g/12c/19c、MySQL 8.0 OCP、Exadata、CDP等认证
墨天轮MVP,ITPUB认证专家
圈内拥有“总监”称号,非著名社恐(社交恐怖分子)全网同名:胖头鱼的鱼缸
ITPUB:yhw1809
除授权转载并标明出处外,均为“非法”抄袭
特性介绍
Oracle AI Database 23.26.2为JSON关系二元性视图新增了验证指令(Validation Directive)功能。验证指令允许开发者以声明式的方式为Duality View 及其底层表附加补充的业务规则逻辑。
验证逻辑存储在数据库中,在对Duality View执行操作(插入、更新、查询)时自动评估执行。这为传统的应用代码或数据库触发器实现业务规则提供了一种声明式的替代方案。
语法介绍
CREATE [ORREPLACE] DIRECTIVE 指令名称
FOR Duality_View 名称
VALIDATE
ON ( SELECT | INSERT | UPDATE )+ -- 可指定一个或多个操作
( BEFOREOBJECT | AFTEROBJECT | ONCOMMIT ) -- 处理阶段
[ (VALIDATE | NOVALIDATE) (ENABLE | DISABLE) ] -- 可选
USING ( SQL表达式 | PLSQL函数 );
处理阶段(Processing Stage):
BEFORE OBJECT - 在文档处理之前验证,失败则操作不执行,语句回滚 AFTER OBJECT - 在文档处理之后验证,失败则回滚语句并报错 ON COMMIT - 在事务提交时验证,失败则提交被拒绝,事务回滚(提供更强的事务一致性保证)
SELECT验证失败 - 抛出错误,不返回验证失败的文档 INSERT/UPDATE验证失败 - 操作被拒绝,语句回滚 ON COMMIT验证失败 - 提交失败,整个事务回滚
验证逻辑支持三种形式:
SQL/JSON表达式:如 json_value(new.data, ‘$.salary’) < 10000 PL/SQL函数:函数签名为 (old_data JSON, new_data JSON) RETURN BOOLEAN new_data:插入/更新后的文档(提议版本) old_data:更新前的文档(原始版本,INSERT 时为 null) 返回 TRUE 表示验证通过,FALSE 表示验证失败 PL/SQL匿名块
VALIDATE/NOVALIDATE 选项:
VALIDATE - 创建指令时验证现有数据(如有不合规数据,创建失败) NOVALIDATE - 创建指令时不验证现有数据(默认)
ENABLE/DISABLE 选项:
ENABLE - 创建后立即生效(默认) DISABLE - 创建后不生效(可用 ALTER DIRECTIVE 启用)
错误码:
ORA-43589: Cannot create validation directive ‘xxxx’: Validation directives creation is not supported under the SYS schema (不能在SYS schema下创建验证指令,使用SYS用户登录切换至其他SCHEMA也会报错) OORA-43591: Validation failed for directive ‘xxxx’ on JSON-relational duality view ‘xxxx’ (验证失败)
限制
不能在 SYS schema 下创建验证指令 验证逻辑必须确定性且无副作用 禁止 DML、ALTER SESSION、COMMIT/ROLLBACK、PRAGMA AUTONOMOUS_TRANSACTION 禁止修改包状态,禁止使用 UTL_HTTP、UTL_TCP、UTL_SMTP 等包 存在验证指令时,并行 DML 和直接加载操作会降级为串行常规 DML
适用场景
业务规则强制执行:例如确保员工薪资在合理范围内(2000 ≤ salary < 10000) 订单状态保护:已发货订单(status = ‘shipped’)不允许添加新的订单项,使用 ON COMMIT 阶段防止并发修改 数据质量管控:查询时验证文档完整性,不返回不符合规则的文档 合规审计:确保插入的文档满足行业合规要求,如金融交易必须包含必要字段 多租户隔离:验证租户不能访问或修改其他租户的数据 替代触发器:将原本在应用层或触发器中实现的验证逻辑下沉到数据库声明式管理
实战演示
创建测试表和视图
CREATE TABLE vd_employees (
emp_id NUMBER PRIMARY KEY,
emp_name VARCHAR2(100),
salary NUMBER,
dept VARCHAR2(30)
);CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW vd_emp_dv AS
SELECT JSON {'_id' : emp_id,
'name' : emp_name,
'salary': salary,
'dept' : dept}
FROM vd_employees WITH (INSERT, UPDATE, DELETE);
测试1:使用SQL表达式对INSERT(BEFORE OBJECT)验证
CREATE DIRECTIVE salary_max_check FOR vd_emp_dv
VALIDATE
ON INSERT
BEFORE OBJECT
USING json_value(new.data, '$.salary') < 10000;INSERT INTO vd_emp_dv VALUES ('{"_id":1, "name":"Alice", "salary":5000, "dept":"Engineering"}');
INSERT INTO vd_emp_dv VALUES ('{"_id":2, "name":"Bob", "salary":15000, "dept":"Sales"}');
salary≥10000的无法被插入。
测试2:使用PL/SQL函数对INSERT(BEFORE OBJECT)验证
CREATE OR REPLACE FUNCTION check_min_salary(old_data JSON, new_data JSON)
RETURN BOOLEAN
IS
BEGIN
RETURN json_value(new_data, '$.salary') >= 2000;
END;
/CREATE DIRECTIVE salary_min_check FOR vd_emp_dv
VALIDATE
ON INSERT
BEFORE OBJECT
NOVALIDATE
USING check_min_salary;INSERT INTO vd_emp_dv VALUES ('{"_id":3, "name":"Carol", "salary":3000, "dept":"HR"}');
INSERT INTO vd_emp_dv VALUES ('{"_id":4, "name":"Dave", "salary":1000, "dept":"Sales"}');
salary≥2000的才能被插入。
测试3:UPDATE验证(BEFORE OBJECT)
CREATE DIRECTIVE salary_update_check FOR vd_emp_dv
VALIDATE
ON UPDATE
BEFORE OBJECT
USING json_value(new.data, '$.salary') < 10000;UPDATE vd_emp_dv SET data = JSON_TRANSFORM(data, SET'$.salary' = 8000)
WHERE JSON_VALUE(data, '$._id' RETURNING NUMBER) = 1;UPDATE vd_emp_dv SET data = JSON_TRANSFORM(data, SET'$.salary' = 12000)
WHERE JSON_VALUE(data, '$._id' RETURNING NUMBER) = 1;
修改salary≥10000会失败。
测试4:SELECT验证(AFTER OBJECT)
CREATE OR REPLACE DIRECTIVE no_test_names FOR vd_emp_dv
VALIDATE
ON SELECT
AFTER OBJECT
NOVALIDATE ENABLE
USING json_value(new.data, '$.name') != 'TEST';INSERT INTO vd_employees VALUES (5, 'TEST', 5000, 'Temp');
COMMIT;SELECT data FROM vd_emp_dv WHERE JSON_VALUE(data, '$._id' RETURNING NUMBER) = 5;
SELECT JSON_VALUE(data, '$._id') AS id, JSON_VALUE(data, '$.name') AS name
FROM vd_emp_dv ORDER BY JSON_VALUE(data, '$._id' RETURNING NUMBER);
查询完整数据,对于TEST文档失败。查询单个字段应成功(无SELECT验证)。
查询所有验证指令
SELECT directive_name, object_name, on_clause, processing_stage_clause, status, using_type
FROM user_validation_directives
WHERE object_name = 'VD_EMP_DV'
ORDER BY directive_name;
总结
本期对Oracle AI Database 26ai,23.26.2版本新引入的JSON关系二元性验证指令新特性进行了完整介绍与实战演示
老规矩,知道写了些啥。