ORA-32320 错误本质是物化视图含聚合函数但日志未覆盖相关列,Oracle在FAST刷新前静态校验失败即报错;需重建含全量聚合列的日志并确保SEQUENCE和INCLUDING NEW VALUES启用。
ora-32320 只在 fast 刷新时出现,本质是物化视图定义和日志结构不匹配——不是语法错,而是刷新路径被oracle主动拒绝。
ORA-32320 错误的触发条件
这个错误明确指向「物化视图包含聚合函数,但定义中引用了未被物化视图日志覆盖的列」。Oracle 在快速刷新前会做静态校验:只要发现 AVG()、SUM()、COUNT(*) 等聚合函数作用于某列,而该列没出现在 USER_MVIEW_LOGS 的 SEQUENCE 或 INCLUDING NEW VALUES 列表里,就直接报 ORA-32320: REFRESH FAST of "OWNER"."MV_NAME" cannot be done,根本不尝试执行。
- 常见诱因:建日志时漏加关键列,例如
CREATE MATERIALIZED VIEW LOG ON t WITH ROWID, SEQUENCE;但没指定列名,导致只记录 ROWID 和主键,不记录参与聚合的非主键列 - 隐性陷阱:用
COUNT(*)看似不依赖具体列,但 Oracle 要求日志必须含ROWID且基表不能有NULL值突变(否则无法判断行是否新增/删除) - 注意:该错误与
ON COMMIT无关——即使设为ON DEMAND,手动调用DBMS_MVIEW.REFRESH时仍会校验并报此错
如何确认哪一列缺失日志支持
先查物化视图实际用了哪些列:
SELECT TEXT FROM DBA_VIEWS WHERE VIEW_NAME = 'YOUR_MV_NAME';
再查日志是否覆盖这些列:
SELECT LOG_TABLE, SEQUENCE, PRIMARY_KEY, ROWIDS,
DECODE(INCLUDE_NEW_VALUES, 'Y', 'YES', 'NO') AS INCLUDES_NEW_VALUES,
LOG_TRIGGER
FROM USER_MVIEW_LOGS
WHERE MASTER = 'YOUR_BASE_TABLE';
- 若返回中
SEQUENCE为NO,说明日志不支持按变更顺序应用,AVG()/SUM()必报ORA-32320 - 若
INCLUDES_NEW_VALUES是NO,且聚合函数涉及可空列(如SUM(amount)),则日志无法捕获amount从NULL→100的变化,同样触发该错 - 检查日志列明细:
SELECT COLUMN_NAME FROM USER_MVIEW_LOG_FILTER_COLS WHERE LOG_TABLE = 'MLOG$_YOUR_TABLE';—— 这里必须包含所有被聚合函数直接引用的列名
修复步骤:重建日志 + 调整 MV 定义
不能只改物化视图,必须同步修正日志结构:
- 删旧日志:
DROP MATERIALIZED VIEW LOG ON your_base_table; - 重建带全量列的日志:
CREATE MATERIALIZED VIEW LOG ON your_base_table WITH ROWID, SEQUENCE(col1, col2, amount) INCLUDING NEW VALUES;—— 注意括号内必须列出所有聚合列 - 若原 MV 含
COUNT(*)且基表有NULL值风险,强制加NOT NULL约束或改用COUNT(col)(跳过 NULL 行) - 重建物化视图时避免裸列聚合:
SUM(NVL(amount, 0))比SUM(amount)更安全,且确保amount已在日志列列表中
为什么不能靠 ATOMIC_REFRESH=FALSE 或 parallelism 绕过
这些参数影响的是刷新执行阶段,而 ORA-32320 发生在刷新前的元数据校验阶段。无论你设 atomic_refresh => FALSE 还是 parallelism => 8,Oracle 都不会进入执行环节,直接抛错退出。
真正容易被忽略的是:日志重建后,必须重新收集统计信息(DBMS_STATS.GATHER_TABLE_STATS)并验证 USER_MVIEW_LOGS 中对应记录的 SEQUENCE 和 INCLUDES_NEW_VALUES 字段已变为 YES——否则你以为修好了,其实日志结构没生效。


















