oracle区块链表必须显式指定no drop或no delete保留策略,否则建表报错;仅支持insert操作,哈希算法强制为sha2_512,且需通过dbms_blockchain_table包验证完整性。
create blockchain table 语句必须显式指定保留策略
oracle 21c 的区块链表不是普通堆表的替代品,而是带强制约束的专用结构。你不能只写 create blockchain table t (x int) 就完事——语法会直接报错 ora-00922: missing or invalid option。
必须至少指定 NO DROP 或 NO DELETE 中的一个,否则建表失败。常见错误是漏掉 LOCKED 关键字却误以为默认生效:比如写 NO DELETE UNTIL 7 DAYS AFTER INSERT,实际等效于可被 ALTER TABLE ... DROP COLUMN 修改保留期;只有加上 LOCKED 才真正锁定不可逆。
-
NO DROP控制表本身能否被删:用NO DROP UNTIL 1 DAYS IDLE测试时,只要 24 小时内有新插入,表就无法被DROP TABLE或DROP USER ... CASCADE -
NO DELETE LOCKED表示行数据永不可删(哪怕用DELETE或TRUNCATE);而NO DELETE UNTIL 30 DAYS AFTER INSERT LOCKED允许满 30 天后由 DBA 手动清理过期行 - 哈希算法必须明确指定:
HASHING USING "SHA2_512"是唯一支持选项,"SHA2_256"会报ORA-65145: invalid hash algorithm
INSERT 是唯一允许的 DML,且不能用绑定变量绕过校验
区块链表只接受 INSERT,其他 DML(UPDATE、DELETE、MERGE)全部拒绝,错误信息统一为 ORA-03249: operation not allowed on blockchain table。但更隐蔽的问题在于:PL/SQL 中若用动态 SQL 绑定变量插入,Oracle 会跳过行级哈希完整性校验,导致后续 DBMS_BLOCKCHAIN_TABLE.VERIFY_ROWS 检查失败。
正确做法是拼接字面量值,或改用静态 SQL。例如:
DECLARE v_emp_id NUMBER := 101; v_sal NUMBER := 5000; BEGIN -- ❌ 错误:绑定变量触发校验绕过 EXECUTE IMMEDIATE 'INSERT INTO ledger_emp VALUES (:1, :2)' USING v_emp_id, v_sal; <p>-- ✅ 正确:静态 SQL 或显式拼接(注意 SQL 注入风险需自行过滤) INSERT INTO ledger_emp VALUES (v_emp_id, v_sal); END;</p>
原因在于绑定变量路径不参与 Oracle 内部的哈希链计算上下文,导致 ORABCTAB_HASH$ 字段生成异常。
查询区块链表要避开内部隐藏列的干扰
区块链表自动添加 12 个以 ORABCTAB_ 开头的系统列(如 ORABCTAB_HASH$、ORABCTAB_CREATION_TIME$),它们默认不可见,但一旦在 SELECT * 或 PL/SQL 记录类型中未显式排除,就会引发类型不匹配或截断问题。
典型报错:PLS-00597: expression 'ORABCTAB_HASH$' in the INTO list is of wrong type。解决方法只有两个:
- 始终用显式列名查询,例如
SELECT employee_id, salary FROM ledger_emp,绝不写SELECT * - 若需封装成记录类型,必须按实际业务列定义,不能
%ROWTYPE(它会包含隐藏列) - 检查表结构用
SELECT column_name FROM user_tab_cols WHERE table_name = 'LEDGER_EMP' AND hidden_column = 'NO'过滤出可见列
PL/SQL 验证和审计必须调用 DBMS_BLOCKCHAIN_TABLE 包
区块链表的数据完整性不能靠应用层逻辑保证,Oracle 提供了专用包 DBMS_BLOCKCHAIN_TABLE 做验证。但它的函数不是“调用即生效”,而是有严格前提:
-
VERIFY_ROWS要求当前用户对表有SELECT权限,且表必须处于READ ONLY状态(否则报ORA-65148: table must be read only for verification) -
VERIFY_CHAIN只能校验整条链,不能指定范围;返回TRUE表示从创世块到最新块全部连贯,FALSE则说明某行ORABCTAB_HASH$与前序哈希不匹配 - 审计操作日志必须查
user_blockchain_tables和dba_blockchain_table_audit(后者需SELECT ANY DICTIONARY权限),普通DBA_AUDIT_TRAIL不记录区块链表的插入事件
最容易被忽略的是:验证操作本身不修复数据,只报告结果。一旦 VERIFY_CHAIN 返回 FALSE,唯一办法是重建表并重放原始交易日志——没有在线修复机制。











