胖头鱼的技术专栏-446 26ai新特性实战:JSON关系二元性内联写增强(20260715)
数据库管理446期 2026-07-15
- 胖头鱼的技术专栏-446 26ai新特性实战:(20260715)
- 特性介绍
- 语法介绍
- 使用场景
- 实战演示
- 创建测试表
- 测试1:无条件生成
- 测试2:输入中存在生成字段时报错(无条件)
- 测试3:条件生成(IF MISSING)
- 测试4:在路径表达式中使用case()进行条件生成
- 测试5:从其他field派生值
- 总结
胖头鱼的技术专栏-446 26ai新特性实战:(20260715)
作者:胖头鱼的鱼缸(尹海文) Oracle ACE Pro: Database PostgreSQL ACE 10年+数据库行业经验 拥有OCM 11g/12c/19c、MySQL 8.0 OCP、Exadata、CDP等认证 墨天轮MVP,ITPUB认证专家 圈内拥有“总监”称号,非著名社恐(社交恐怖分子) 全网同名:胖头鱼的鱼缸 ITPUB:yhw1809 除授权转载并标明出处外,均为“非法”抄袭特性介绍
Oracle AI Database 23.26.2 引入了JSON Relational Duality View(JSON关系二元性视图)内联写增强(Inline Write Augmentation)功能。当通过 Duality View 插入或更新文档时,该功能可以自动创建输入文档中不存在的额外字段,并为其赋值。
这意味着开发者可以:
- 为缺失的字段自动提供默认值
- 对传入的值进行自动转换
- 根据文档中其他字段的值动态计算生成字段的值
两种生成模式:
无条件生成(Unconditional)
字段始终被生成,如果输入文档中已包含该字段则报错
适用于:审计字段、计算字段、不允许用户修改的系统字段
错误码:ORA-42727 / JZN-00695(字段已存在时)条件生成(IF MISSING)
仅当字段在输入文档中缺失时才生成,否则使用输入文档中的值
适用于:默认值、可选的派生字段
生成表达式支持:
- 常量值:PATH ‘1000’
- 派生值:PATH ‘$.otherField[0]’(从其他字段提取)
- case() 条件:PATH ‘case(@.salary>60000, 1000, 500)’
- decode() 匹配:PATH ‘decode(@.tips, 0, 0, 100)’
- 字符串操作:PATH ‘$.creditCard.substr(15)’
语法介绍
SQL DDL:
'field':columnGENERATEDONWRITEUSINGPATH'expression''field':columnGENERATEDONWRITEIFMISSINGUSINGPATH'expression'还可与读增强(READ augmentation)组合使用,以及将字段设为 HIDDEN(不出现在返回的文档中,但值持久化到列)。
GraphQL:
field:column@generated(path:"expression",on:"write")-- 无条件field:column@generated(path:"expression",on:"missing")-- 条件field:column@generated(path:"expression",on:"write")@hidden使用场景
下面是一些可以使用该特性的实际生产业务场景:
- 薪酬管理:根据薪资水平自动计算奖金(case/decode 条件逻辑)。例如:salary > 60000 的员工 bonus = 1000,否则 500
- 数据脱敏:从信用卡号中提取最后四位存储,前端展示时重新拼接掩码。creditCard 字段写入时自动提取 ccLast4(HIDDEN 字段)
- 默认值填充:新员工未指定部门时自动分配默认部门
- 计算字段:从 JSON 数组中提取首元素作为优先级标记。例如:shiftPref 数组的第一个元素作为 shiftPrio
- 审计追踪:自动为每条记录填充创建时间、版本号等系统字段
- API 后端:REST API 接收部分字段的文档,数据库自动补全其他字段
实战演示
同之前一样,使用用户NFTEST,已授权DB_DEVELOPER_ROLE角色,测试操作均在NFTEST用户下执行。
创建测试表
CREATETABLEdva_employees(emp_id NUMBERPRIMARYKEY,emp_name VARCHAR2(100),salary NUMBER,bonus NUMBER,dept_code VARCHAR2(10),shift_pref JSON,shift_prio VARCHAR2(50));测试1:无条件生成
插入数据是“bonus”字段不指定值自动生成值500。
CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW dva_emp_const AS SELECT JSON {'_id' : emp_id, 'name' : emp_name, 'salary' : salary, 'bonus' : bonus GENERATED ON WRITE USING PATH '500'} FROM dva_employees WITH (INSERT, UPDATE, DELETE); INSERT INTO dva_emp_const VALUES ('{"_id":1, "name":"Alice", "salary":50000}'); SELECT data FROM dva_emp_const WHERE JSON_VALUE(data, '$._id' RETURNING NUMBER) = 1; SELECT * FROM dva_employees;bouns列均赋值500。
测试2:输入中存在生成字段时报错(无条件)
INSERTINTOdva_emp_constVALUES('{"_id":2, "name":"Bob", "salary":60000, "bonus":1000}');因为无条件的限制,无法在bonus字段有值时成功插入数据。
测试3:条件生成(IF MISSING)
CREATEORREPLACEJSON RELATIONAL DUALITYVIEWdva_emp_missingASSELECTJSON {'_id': emp_id,'name': emp_name,'salary': salary,'bonus': bonus GENERATEDONWRITEIFMISSINGUSINGPATH'500'}FROMdva_employeesWITH(INSERT,UPDATE,DELETE);INSERTINTOdva_emp_missingVALUES('{"_id":3, "name":"Carol", "salary":70000}');INSERTINTOdva_emp_missingVALUES('{"_id":4, "name":"Dave", "salary":80000, "bonus":2000}');SELECTdataFROMdva_emp_missingWHEREJSON_VALUE(data,'$._id'RETURNINGNUMBER)IN(3,4)ORDERBYJSON_VALUE(data,'$._id'RETURNINGNUMBER);bonus字段指定与否都可以插入。
测试4:在路径表达式中使用case()进行条件生成
当salary>60000时,bonus为1000,否则为500。
CREATEORREPLACEJSON RELATIONAL DUALITYVIEWdva_emp_caseASSELECTJSON {'_id': emp_id,'name': emp_name,'salary': salary,'bonus': bonus GENERATEDONWRITEUSINGPATH'case(@.salary>60000,1000,500)'}FROMdva_employeesWITH(INSERT,UPDATE,DELETE);INSERTINTOdva_emp_caseVALUES('{"_id":10, "name":"Eve", "salary":45000}');INSERTINTOdva_emp_caseVALUES('{"_id":11, "name":"Frank", "salary":75000}');SELECTdataFROMdva_emp_caseWHEREJSON_VALUE(data,'$._id'RETURNINGNUMBER)IN(10,11)ORDERBYJSON_VALUE(data,'$._id'RETURNINGNUMBER);测试5:从其他field派生值
shiftPri是从shiftPref属组的第一个值派生
CREATEORREPLACEJSON RELATIONAL DUALITYVIEWdva_emp_derivedASSELECTJSON {'_id': emp_id,'name': emp_name,'salary': salary,'shiftPref': shift_pref,'shiftPrio': shift_prio GENERATEDONWRITEUSINGPATH'$.shiftPref[0]'}FROMdva_employeesWITH(INSERT,UPDATE,DELETE);INSERTINTOdva_emp_derivedVALUES('{"_id":20, "name":"Grace", "salary":90000, "shiftPref":["night","day","flex"]}');SELECTdataFROMdva_emp_derivedWHEREJSON_VALUE(data,'$._id'RETURNINGNUMBER)=20;-- 验证关系表中数据SELECTemp_id,emp_name,shift_pref,shift_prioFROMdva_employeesWHEREemp_id=20;总结
本期对Oracle AI Database 26ai,23.26.2版本新引入的JSON关系二元性内联写增强新特性进行了完整介绍与实战演示。
老规矩,知道写了些啥。
