【问题标题】:Cannot Set ON COMMIT refresh attribute for Materialized View with PIVOT clause无法使用 PIVOT 子句为物化视图设置 ON COMMIT 刷新属性
【发布时间】:2020-05-10 06:55:54
【问题描述】:

我正在尝试创建以下实体化视图,但出现此错误:

ORA-12054: 无法为实体化视图设置 ON COMMIT 刷新属性

我在提交时使用完全刷新,因为视图中引用的表每个月只有少数几次提交,并且更新只会针对几条记录。我们的团队决定完全刷新提交是要走的路。

这里是 DDL:

CREATE MATERIALIZED VIEW TBLEDW_UANDC_PIVOT
BUILD IMMEDIATE
REFRESH COMPLETE ON COMMIT
ENABLE QUERY REWRITE
  AS
SELECT * FROM 
  (SELECT DISTINCT UC.MAC_CD, UC.GCN_INDEX, UC.GCN_CD, UC.PKG_SZ, UC.U_C_RATE, UC.U_C_AMT FROM 
DMT.TBLEDW_UANDC UC) 
PIVOT 
(SUM(U_C_AMT) FOR (U_C_RATE) IN (10 AS UCA, 30 AS UCB, 50 AS UCC, 70 AS UCD, 90 AS UCE));

我无法弄清楚为什么会发生此错误,感谢您提供任何见解!

【问题讨论】:

  • 你能创建一个没有PIVOT 子句的REFRESH ON COMMIT 物化视图吗?我问是因为我想知道您是否拥有必要的特权。
  • @BobJarvis-ReinstateMonica 我确实需要使用 PIVOT 子句,并且此脚本由具有特权的 DBA 管理。
  • 您有ON COMMIT REFRESH 权限吗? DMT.TBLEDW_UANDC 是基于远程表的视图吗?
  • @WernfriedDomscheit 我的运行脚本的 DBA 有权限,但是是的,这是基于远程表的。

标签: sql oracle oracle11g


【解决方案1】:

以下是 PIVOT 不工作的示例以及如何使用 DECODE 解决此问题。

在我的博客 https://connor-mcdonald.com/2019/10/02/a-refreshing-look-at-pivot/ 上对示例进行完整评论

SQL> create table patient
  2   ( region      int,
  3     office       int,
  4     patient      int,
  5     some_date date );

Table created.

SQL>
SQL> alter table patient add primary key ( region, office, patient );

Table altered.

SQL>
SQL> insert into patient values (1,1,1,sysdate);

1 row created.

SQL> insert into patient values (1,1,2,sysdate);

1 row created.

SQL> insert into patient values (1,1,3,sysdate);

1 row created.

SQL>
SQL> create table patient_attrib
  2   ( region      int,
  3     office       int,
  4     patient      int,
  5     property      varchar2(10),
  6     val           number);

Table created.

SQL>
SQL>
SQL> alter table patient_attrib add primary key ( region, office, patient, property );

Table altered.

SQL> alter table patient_attrib add constraint patient_attrib_fk
  2  foreign key ( region,office,patient) references patient (region,office,patient);

Table altered.

SQL>
SQL> insert into patient_attrib values (1,1,2,'weight',60);

1 row created.

SQL> insert into patient_attrib values (1,1,2,'height',1);

1 row created.

SQL> insert into patient_attrib values (1,1,2,'bp',2);

1 row created.

SQL> insert into patient_attrib values (1,1,2,'heart',3);

1 row created.

SQL> insert into patient_attrib values (1,1,2,'chol',4);

1 row created.

SQL> insert into patient_attrib values (1,1,2,'fatpct',5);

1 row created.

SQL>
SQL> insert into patient_attrib values (1,1,3,'weight',61);

1 row created.

SQL> insert into patient_attrib values (1,1,3,'height',1.1);

1 row created.

SQL> insert into patient_attrib values (1,1,3,'bp',2.1);

1 row created.

SQL> insert into patient_attrib values (1,1,3,'heart',3.1);

1 row created.

SQL> insert into patient_attrib values (1,1,3,'chol',4.1);

1 row created.

SQL> insert into patient_attrib values (1,1,3,'fatpct',5.1);

1 row created.

SQL> select region, office, patient, some_date, weight_val, height_val, bp_val, heart_val, chol_val, fatpct_val
  2  from
  3  (
  4  select h.*, hs.property, hs.val
  5  from   patient h,
  6         patient_attrib hs
  7  where  h.region = hs.region
  8  and    h.office  = hs.office
  9  and    h.patient = hs.patient
 10  )
 11  pivot ( sum(val) as val for ( property ) in ('weight' as weight, 'height' as height, 
 12       'bp' as bp, 'heart' as heart, 'chol' as chol, 'fatpct' as fatpct));

    REGION     OFFICE    PATIENT SOME_DATE WEIGHT_VAL HEIGHT_VAL     BP_VAL  HEART_VAL   CHOL_VAL FATPCT_VAL
---------- ---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
         1          1          2 02-OCT-19         60          1          2          3          4          5
         1          1          3 02-OCT-19         61        1.1        2.1        3.1        4.1        5.1

SQL> create materialized view log on patient
  2    with sequence, rowid (region,office,patient,some_date) including new values
  3  /

Materialized view log created.

SQL>
SQL> create materialized view log on patient_attrib
  2    with sequence, rowid (region,office,patient,property, val) including new values
  3  /

Materialized view log created.

SQL> create materialized view MV
  2  refresh fast
  3  -- on commit
  4  as
  5  select region, office, patient, some_date, weight_val, height_val, bp_val, heart_val, chol_Val, fatpct_val
  6  from
  7  (
  8  select h.*, hs.property, hs.val
  9  from   patient h,
 10         patient_attrib hs
 11  where  h.region = hs.region
 12  and    h.office  = hs.office
 13  and    h.patient = hs.patient
 14  )
 15  pivot ( sum(val) as val for ( property ) in ('weight' as weight, 'height' as height, 
 16          'bp' as bp, 'heart' as heart, 'chol' as chol, 'fatpct' as fatpct));
create materialized view MV
*
ERROR at line 1:
ORA-12015: cannot create a fast refresh materialized view from a complex query

SQL> select h.region, h.office, h.patient, h.some_date,
  2         sum(decode(hs.property, 'weight', hs.val, 0)) weight_val,
  3         sum(decode(hs.property, 'height', hs.val, 0)) height_val,
  4         sum(decode(hs.property, 'bp', hs.val, 0)) bp_val,
  5         sum(decode(hs.property, 'heart', hs.val, 0)) heart_val,
  6         sum(decode(hs.property, 'chol', hs.val, 0)) chol_Val,
  7         sum(decode(hs.property, 'fatpct', hs.val, 0)) fatpct_val
  8  from   patient h,
  9         patient_attrib hs
 10  where  h.region = hs.region
 11  and    h.office  = hs.office
 12  and    h.patient = hs.patient
 13  group by h.region, h.office, h.patient, h.some_date;

    REGION     OFFICE    PATIENT SOME_DATE WEIGHT_VAL HEIGHT_VAL     BP_VAL  HEART_VAL   CHOL_VAL FATPCT_VAL
---------- ---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
         1          1          2 02-OCT-19         60          1          2          3          4          5
         1          1          3 02-OCT-19         61        1.1        2.1        3.1        4.1        5.1

2 rows selected.

SQL> create materialized view MV
  2  refresh fast
  3  on commit
  4  as
  5  select h.region, h.office, h.patient, h.some_date,
  6         count(*) c,
  7         count(decode(hs.property, 'weight', hs.val, 0)) weight_cnt,
  8         count(decode(hs.property, 'height', hs.val, 0)) height_cnt,
  9         count(decode(hs.property, 'bp', hs.val, 0)) bp_cnt,
 10         count(decode(hs.property, 'heart', hs.val, 0)) heart_cnt,
 11         count(decode(hs.property, 'chol', hs.val, 0)) chol_cnt,
 12         count(decode(hs.property, 'fatpct', hs.val, 0)) fatpct_cnt,
 13         sum(decode(hs.property, 'weight', hs.val, 0)) weight_val,
 14         sum(decode(hs.property, 'height', hs.val, 0)) height_val,
 15         sum(decode(hs.property, 'bp', hs.val, 0)) bp_val,
 16         sum(decode(hs.property, 'heart', hs.val, 0)) heart_val,
 17         sum(decode(hs.property, 'chol', hs.val, 0)) chol_Val,
 18         sum(decode(hs.property, 'fatpct', hs.val, 0)) fatpct_val
 19  from   patient h,
 20         patient_attrib hs
 21  where  h.region = hs.region
 22  and    h.office  = hs.office
 23  and    h.patient = hs.patient
 24  group by h.region, h.office, h.patient, h.some_date;

Materialized view created.

【讨论】:

  • 这太好了,康纳,也请阅读您的博文!这也适用于完全刷新吗?
  • 会的,但如果你正在做一个全新的,那么你不太可能在提交时这样做
【解决方案2】:

根据您的评论,请参阅ON COMMIT Clause

对 COMMIT 刷新的限制

  • 包含对象类型或 Oracle 提供的类型的物化视图不支持此子句。

  • 具有远程表的物化视图不支持此子句。

  • 如果您指定此子句,则您不能随后在此物化视图的任何主表上执行分布式事务。 例如,您不能通过从 远程表。 ON DEMAND 子句没有对 主表上的后续分布式事务。

所以,你不能使用它。

【讨论】:

  • 我也在网上看到了这些刷新限制,但我很困惑为什么该表被视为“远程”?所有这些都发生在同一个模式“DMT”中。是什么让桌子“偏远”?
  • 通过 DB Link 访问远程平均表
【解决方案3】:

ON COMMIT 子句创建了一个快速 可刷新的 mview。带有PIVOT 子句的实体化视图不能快速刷新。

我认为您可以通过使用dbms_mview.explain_mview 并检查列以了解为什么它不能快速刷新来自己判断。

【讨论】:

    猜你喜欢
    • 2016-12-24
    • 2016-01-22
    • 2016-12-11
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 2012-07-03
    相关资源
    最近更新 更多