error creating materialized view in oracle - ORA-12052 - oracle

good night i am trying to create a materialized view in oracle and i have the following error message. I know there are several restrictions but I can't identify what the error is. please appreciate your help.
obs:
-the update method must be incremental.
none of the tables have primary keys and I can't create them because I don't have access.
CREATE MATERIALIZED VIEW LOG ON ordenes
WITH ROWID
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW LOG ON tabla_hija
WITH ROWID
INCLUDING NEW VALUES;
create materialized view vm_prueba2
refresh fast on demand
with rowid
as
select ordenid,o.empleadoid,o.clienteid,fechaorden,descuento,nvl(c.desccripcion,'')as ddesc,e.desccripcion
from ordenes o,tabla_hija c,tabla_hija e
where
( o.clienteid=c.valor(+) and c.id_tabla=1 or c.valor is null ) and
( o.empleadoid=e.valor(+) and e.id_tabla=2 or e.valor is null )order by ordenid asc;
Informe de error -
ORA-12052:
12052. 00000 - "cannot fast refresh materialized view %s.%s"
*Cause: Either ROWIDs of certain tables were missing in the definition or
the inner table of an outer join did not have UNIQUE constraints on
join columns.
*Action: Specify the FORCE or COMPLETE option. If this error is got
during creation, the materialized view definition may have be
changed. Refer to the documentation on materialized views.

"ROWIDs of certain tables were missing in the definition"
You need to include the rowids of each source table in your materialized view:
create materialized view vm_prueba2
refresh fast on demand
with rowid
as
select
o.rowid o_rowid,
c.rowid c_rowid,
e.rowid e_rowid,
ordenid,
o.empleadoid,
o.clienteid,
fechaorden,
descuento,
nvl(c.desccripcion,'') as ddesc,
e.desccripcion
from ordenes o, tabla_hija c, tabla_hija e
where
( o.clienteid=c.valor(+) and c.id_tabla=1 or c.valor is null ) and
( o.empleadoid=e.valor(+) and e.id_tabla=2 or e.valor is null );
I would also recommend not sorting your MV content, as it will add unnecessary overhead to the generation. The order of the rows stored on disk doesn't matter, and it will generate a lot of extra disk I/O while it performs the sort in the Temp tablespace.
The sort will most likely be dropped by Oracle for the refreshes anyway, as Oracle creates its own SQL automatically and only uses yours for the initial MV creation. Save your sorts for client/user queries.

Related

change fields in materialized view - oracle

Goodnight,
I have a working materialized view,to which I will add 15 left join similar to the ones in the example lines below, is there a way to edit it and hide the rowids?,If I replace the rowid with primary key, could I omit them?
because I would have to put 15 additional rowids, and it would be visually impractical. is there a way to make it only show the fields I want and not the rowsid,
How else could I change it to not have unnecessary columns, is there a way to handle incremental loads without having to do all a complex stored procedures?
this way is quite simple for handling incremental loads, it is mandatory that the materialized view be incremental (refresh fast)
thank you very much.
Regards.
create materialized view vm_prueba2
refresh fast on demand
with rowid as
select
o.rowid o_rowid,
c.rowid c_rowid,
e.rowid e_rowid,
ordenid,
o.empleadoid,
o.clienteid,
fechaorden,
descuento,
nvl(c.desccripcion,'') as ddesc,
e.desccripcion
from ordenes o, tabla_hija c, tabla_hija e
where
( o.clienteid=c.valor(+) and c.id_tabla=1 or c.valor is null ) and
( o.empleadoid=e.valor(+) and e.id_tabla=2 or e.valor is null )
create a materialized view, with all the rowids
create a view on a top on that materialized view which shows only columns you want
that way, you'd "hide" everything you don't need (rowids, right?)
which also means that you'd actually use the view in selects, not the materialized view
materialized view refresh would work as usual
For example:
create materialized view vm_prueba2
refresh fast on demand
with rowid as
select
o.rowid o_rowid,
...
from ...;
-- a view would select only some columns from the materialized view:
create or replace view v_vm_prueba2 as
select empleadoid,
clienteid,
fechaorden
from vm_prueba2;

Materialized View Refresh with changing synonym pointer in SQL

I have two tables, TABLE_1 and TABLE_2. Then we have a synonym called TABLE that points to either TABLE_1 or TABLE_2. When TABLE_1 is active, an ETL populates TABLE_2 and when the run is complete, it switches the TABLE synonym to TABLE_2 to make it the active table. Then I have a materialized view that does something like this as the SQL: select * from TABLE. What I am seeing happen is that after the materialize view runs the first time, it caches the actual table the synonym is pointing too. So when the ETL runs and flips the synonym to point at TABLE_2, when a complete refresh is done on the materialized view, it still thinks the synonym is pointed at TABLE_1. Why when I do a complete refresh does the materialized view not pick up the new synonym pointer to TABLE_2?
Here is a workaround to Oracle's bug:
alter materialized view MV_NAME nocache;
BEGIN DBMS_SNAPSHOT.REFRESH( MV_NAME,'C'); end;
alter materialized view MV_NAME cache;
I cannot find anything useful in Oracle documentation but just enable the logic:
I firstly create materialized view
In reality to support this materialized view Oracle makes the TABLE with some specific structure (dependent on your query structure) and the rule to refresh the table (as far as I remember it is called SUMMARY, but the name does not play any role here)
I change synonym target to the table which has another structure
The new target table is not "fitting" to the previous structure (e.g. it has totally different amount/data types of columns), the previous structure is invalid then and not working anymore. The underground table must be recreated then.
That's why I would say it is the only way to prevent the errors: reference the real target instead of synonym for creating materialized view.
So, the answer is: because the materialized view is a static table-like object dependent on the data set it is selecting; that's why to prevent the inconsistencies materialized view references the real object.
Sometimes I really wonder how many details Oracle hides inside.

Query too complex for a simple join [duplicate]

So I'm pretty sure Oracle supports this, so I have no idea what I'm doing wrong. This code works:
CREATE MATERIALIZED VIEW MV_Test
NOLOGGING
CACHE
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS
SELECT V.* FROM TPM_PROJECTVERSION V;
If I add in a JOIN, it breaks:
CREATE MATERIALIZED VIEW MV_Test
NOLOGGING
CACHE
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS
SELECT V.*, P.* FROM TPM_PROJECTVERSION V
INNER JOIN TPM_PROJECT P ON P.PROJECTID = V.PROJECTID
Now I get the error:
ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view
I've created materialized view logs on both TPM_PROJECT and TPM_PROJECTVERSION. TPM_PROJECT has a primary key of PROJECTID and TPM_PROJECTVERSION has a compound primary key of (PROJECTID,VERSIONID). What's the trick to this? I've been digging through Oracle manuals to no avail. Thanks!
To start with, from the Oracle Database Data Warehousing Guide:
Restrictions on Fast Refresh on Materialized Views with Joins Only
...
Rowids of all the tables in the FROM list must appear in the SELECT
list of the query.
This means that your statement will need to look something like this:
CREATE MATERIALIZED VIEW MV_Test
NOLOGGING
CACHE
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS
SELECT V.*, P.*, V.ROWID as V_ROWID, P.ROWID as P_ROWID
FROM TPM_PROJECTVERSION V,
TPM_PROJECT P
WHERE P.PROJECTID = V.PROJECTID
Another key aspect to note is that your materialized view logs must be created as with rowid.
Below is a functional test scenario:
CREATE TABLE foo(foo NUMBER, CONSTRAINT foo_pk PRIMARY KEY(foo));
CREATE MATERIALIZED VIEW LOG ON foo WITH ROWID;
CREATE TABLE bar(foo NUMBER, bar NUMBER, CONSTRAINT bar_pk PRIMARY KEY(foo, bar));
CREATE MATERIALIZED VIEW LOG ON bar WITH ROWID;
CREATE MATERIALIZED VIEW foo_bar
NOLOGGING
CACHE
BUILD IMMEDIATE
REFRESH FAST ON COMMIT AS SELECT foo.foo,
bar.bar,
foo.ROWID AS foo_rowid,
bar.ROWID AS bar_rowid
FROM foo, bar
WHERE foo.foo = bar.foo;
Have you tried it without the ANSI join ?
CREATE MATERIALIZED VIEW MV_Test
NOLOGGING
CACHE
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS
SELECT V.*, P.* FROM TPM_PROJECTVERSION V,TPM_PROJECT P
WHERE P.PROJECTID = V.PROJECTID
You will get the error on REFRESH_FAST, if you do not create materialized view logs for the master table(s) the query is referring to. If anyone is not familiar with materialized views or using it for the first time, the better way is to use oracle sqldeveloper and graphically put in the options, and the errors also provide much better sense.
The key checks for FAST REFRESH includes the following:
1) An Oracle materialized view log must be present for each base table.
2) The RowIDs of all the base tables must appear in the SELECT list of the MVIEW query definition.
3) If there are outer joins, unique constraints must be placed on the join columns of the inner table.
No 3 is easy to miss and worth highlighting here
USE THIS CODE
CREATE MATERIALIZED VIEW MV_ptbl_Category2
BUILD IMMEDIATE
REFRESH FORCE
ON COMMIT
AS
SELECT *
FROM ptbl_Category2;
Note- MV_ptbl_Category2 is the Materialized view name
Ptbl is the table name.

Oracle materialized view question

I have a table that holds information about different events, for example
CREATE TABLE events (
id int not null primary key,
event_date date, ...
)
I realized that 90% of all queries access only today events; the older rows are stored for history and eventually moved to an archive table.
However, events table is still large, and I wonder if I can improve the performance by creating a materialized view that has something like WHERE event_date = trunc(sysdate) and maybe index on event_date ? Is it allowed at all?
Thanks
yes this is allowed see "primary key materialized view":
Primary key materialized views may contain a subquery so that you can
create a subset of rows at the remote materialized view site
and "complex materialized view"
If you refresh rarely and want faster query performance, then use
Method A (complex materialized view).
If you refresh regularly and can sacrifice query performance, then use Method B (simple materialized view).
at http://download.oracle.com/docs/cd/B10500_01/server.920/a96567/repmview.htm
In your example chances are good IMHO that this is not a "complex materialized view":
CREATE MATERIALIZED VIEW events_today REFRESH FAST AS
SELECT * FROM EVENT WHERE event_date = trunc(sysdate);
Just try it and see if Oracle accepts it with the REFRESH FAST clause.
EDIT - another option:
Depending on your DB Edition (Enterprise + Partitioning) and Version (11gR2) you could use a new Oracle feature called INTERVAL partitioning to define "daily partitions" within the existing table. This way most of your queries get alot faster without effectively duplicating the data - see http://www.oracle.com/technetwork/database/options/partitioning/twp-partitioning-11gr2-2009-09-130569.pdf

Oracle - Materialized View, can this MV be fast refreshable?

I have a materialized view that looks somewhat like the following and I'm wondering if there is anyway to have this materialized view 'fast' refreshable? Basically, I'm asking the following:
Can a materialized view contain oracle functions such as COALESCE, NVL, NVL2, etc and still be fast refreshable
Can a materialized view contain functions that I have made and still be fast refreshable.
Can a materialized view contain joins to derived tables and still be fast refreshable?
I checked the Oracle documentation about this, and it did not list these restrictions, however after testing the case below on my own system, I don't believe it is possible.
Oracle version: 10g
SELECT COALESCE (col1, col2),
myOracleFunction(col3, col4)
FROM tableA a
LEFT OUTER JOIN
(SELECT id, MAX (sample_key) prim_sam_key
FROM table_sample
GROUP BY id
HAVING COUNT (1) = 1) b ON a.id = b.id;
Requirements from the link you provided that you're missing:
COUNT(*) must be specified.
The SELECT list must contain all GROUP BY columns.
Also, the following requirement indicates that, for your query, a fast refresh will only be possible if table_sample has been updated, but tableA has not:
Materialized aggregate views with outer joins are fast refreshable
after conventional DML and direct loads, provided only the outer table
has been modified. Also, unique constraints must exist on the join
columns of the inner join table. If there are outer joins, all the
joins must be connected by ANDs and must use the equality (=)
operator.
Finally, when asking about materialized views, it is always a good idea to state exactly what materialized view logs you have created.

Resources