ORÁCULO:A visualização materializada não funciona ao usar LEFT JOIN
-
19-09-2019 - |
Pergunta
Quero criar uma MATERIALIZED VIEW a partir de um LEFT JOIN de 2 tabelas.No entanto, o seguinte me dá um erro:
SELECT field1
FROM table_1 a
LEFT JOIN table_2 b
ON a.field1=b.field2
ORA-12054:não é possível definir o atributo de atualização ON COMMIT para a visualização materializada
No entanto, o seguinte funciona:
SELECT field1
FROM table_1 a, table_2 b
WHERE a.field1=b.field2
Alguém tem alguma idéia de por que isso está acontecendo.
Obrigado pela ajuda
Solução
Existem duas condições que não são satisfeitas para que a visualização materializada seja atualizada rapidamente.A primeira é que você não especificou as colunas rowid de todas as tabelas envolvidas.E a segunda é uma restrição não documentada:Junções ANSI não são suportadas.
Aqui está um exemplo com DEPT sendo tabela_1, alias a e EMP sendo tabela_2, alias b:
SQL> create materialized view log on emp with rowid
2 /
Materialized view log created.
SQL> create materialized view log on dept with rowid
2 /
Materialized view log created.
SQL> create materialized view empdept_mv
2 refresh fast on commit
3 as
4 select a.deptno
5 from dept a
6 left join emp b on (a.deptno = b.deptno)
7 /
from dept a
*
ERROR at line 5:
ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view
Isso imita sua situação.Primeiro adicione o rowid:
SQL> create materialized view empdept_mv
2 refresh fast on commit
3 as
4 select a.rowid dept_rowid
5 , b.rowid emp_rowid
6 , a.deptno
7 from dept a
8 left join emp b on (a.deptno = b.deptno)
9 /
from dept a
*
ERROR at line 7:
ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view
Ainda assim, não é possível atualizar rapidamente, devido às junções ANSI.Convertendo para sintaxe de junção externa de estilo antigo:
SQL> create materialized view empdept_mv
2 refresh fast on commit
3 as
4 select a.rowid dept_rowid
5 , b.rowid emp_rowid
6 , a.deptno
7 from dept a
8 , emp b
9 where a.deptno = b.deptno (+)
10 /
Materialized view created.
E para provar que funciona:
SQL> select * from empdept_mv
2 /
DEPT_ROWID EMP_ROWID DEPTNO
------------------ ------------------ ----------
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAA 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAB 30
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAC 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAD 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAE 30
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAF 30
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAG 10
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAH 20
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAI 10
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAJ 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAK 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAL 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAM 20
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAN 10
AAARhmAAEAAAAI/AAD 40
15 rows selected.
SQL> insert into dept values (50,'IT','UTRECHT')
2 /
1 row created.
SQL> commit
2 /
Commit complete.
SQL> select * from empdept_mv
2 /
DEPT_ROWID EMP_ROWID DEPTNO
------------------ ------------------ ----------
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAA 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAB 30
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAC 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAD 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAE 30
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAF 30
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAG 10
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAH 20
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAI 10
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAJ 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAK 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAL 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAM 20
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAN 10
AAARhmAAEAAAAI/AAD 40
AAARhmAAEAAAAI7AAA 50
16 rows selected.
A restrição de sintaxe ANSI-join é mencionada no ponto 6 em esta postagem do blog.
Atenciosamente, Rob.
Outras dicas
Como este é um post antigo; Não mencionou uma solução completa.
- A tabela que está unida externa deve ter uma chave primária, conforme mencionado no Oracle Doc.
- A consulta não deve ter outras restrições, ou seja, não deve ter nenhum critério de filtro em
WHERE
Cláusula, apenas as junções; Nem pode terCASE
/DECODE
declarações emSELECT
cláusula;GROUP BY
,SUM()
,COUNT()
e tal é permitido, no entanto.
No exemplo acima do exemplo, a consulta funcionará se uma chave primária for criada na tabela de departamento na coluna ID do departamento.
Seguiu as seguintes instruções para fazer dbms_mview.explain_mview funcionar:http://www.sqlsnippets.com/en/topic-12884.html
Capaz de:
Refresh_complete
Não é capaz de:
Refresh_fast
Refresh_fast_after_insert
Visualização em linha ou subconstração da lista não suportada para este tipo MV
Refresh_fast_after_insert
Visualização em linha ou subconstração da lista não suportada para este tipo MV
Refresh_fast_after_insert
Visualizar ou subconstar na lista
Refresh_fast_after_onetab_dml
Veja o motivo pelo qual refresh_fast_after_insert está desativado
Mv_report
Refresh_fast_after_any_dml
Veja o motivo pelo qual refresh_fast_after_onetab_dml está desativado