Oracle Materialized View: update MVs in the remote db? - oracle

I created a fast refresh MV in a remote db by using a syntax like follows:
CREATE MATERIALIZED VIEW MV_TAB1
REFRESH FAST WITH PRIMARY KEY
START WITH SYSDATE NEXT SYSDATE+(5/1440) /* 5 MINUTES */
FOR UPDATE AS
SELECT * FROM TAB1#SOURCE_DB;
Now in the remote db where the MV_TAB1 was created, is it possible to update the MV_TAB1 and keep the update even after the refresh? My testing shows that after each refresh, my update on MV_TAB1 is gone. Is there any way to keep this local update? If yes,how?
Thanks,
Amos

MV_TAB1 is an image of TAB1#SOURCE_DB, so you can't have it in the same time like TAB1 and different to TAB1.
If you update some rows on destination table and then update them in the source, the refresh will overwrite them. If you dont update them in the source they will remain updated ONLY if you use refresh fast. A refresh complete will delete/truncate the remote table and reinsert all rows.
UPDATE: If you want updates on remote table to have priority over the refresh, you can to some tricks:
1) keep the MV as it is and do updates(and inserts) on a sister table with the same DDL. The query, instead of MV, will use both tables, something like:
select nvl(a.key, b.key), decode(a.key, null, b.col, a.col)
from tab1_sister a
full join mv_tab1 b on (a.key = b.key);
2) Add columns to the MV_TAB1(duplicate them, except the key) and do the updates on those columns (it is possible that MV must be with prebuilt table). If the additional columns are completed, use them, otherwise use the original columns updated by the refresh.

Related

Turning Oracle Materialized View to Table and back again

We have a materialized view (MV) on Oracle 19c. Its data is updated/refreshed by scheduler job every day.
Because of some maintenance work that may last for more than 6 months, I would like to update some data inside it manually. However, manual update is forbidden on MV.
It may sound stupid but I am planning to:
Disable to the scheduler job
Turn the MV into table (DROP MATERIALIZED VIEW .. PRESERVE TABLE; )
Then we can update the table data manually for our maintenance work.
After the maintenance work, I would:
Turn the table back to MV
Re-enable the scheduler job to refresh the data
So the question is... how do I turn the table back to MV SAFELY in my case? It is easy to turn MV into table but I have never heard anyone doing it the other way round.
By safely, I mean that the reverted MV is back to before without lost of behaviours/properties.
If I turn the MV to table and then back to MV, would the index still work for both the table and the MV without affected?
Similarly, if we already have a synonym for the MV, would this synonym still work after converting to table and back to MV again?
Do I need re-grant any user privileges to the table and later for the MV again?
Note: I am aware that after turning the table back to MV, the data get refreshed and our manual data would be lost. That is acceptable for us because we just want the manual data to stay during the maintenance period.
If there are other suggestions/alternatives, I am happy to hear.
Combining synonym, patch table and views might be a good solution for temporary situation as suggested.
And then..
You can safely recreate materialized view with
CREATE MATERIALIZED VIEW testmv ON PREBUILT TABLE ...
Indexes can be used till refresh. You don't need to re-grant user privileges
Synonyms that crated previously for MV still works after creating MV from prebuilt table.
What is the reason to update some data inside the mview? Maybe you need a table, not a mview. Just refresh the materialized view to update the data, or change the related SQL to reflect the dataset you want. Other way it would be as inconsistent state.
Turn the table back to MV
If you understand that after that step, the MV is refreshed with the life data and your changes to the underlaying table are lost, it's OK.
Another way to do the job is to access the MV through a VIEW, and changes the definition of the VIEW for the maintenance work (conceptually "select from MV where not exists (select FROM PATCH) UNION ALL select from PATCH"), and putting it back to "select FROM MV" when done).
(And note that truncate PATCH will have the same effect, and you don't have to change the VIEW...)

AUTO-Scynhronize a table based on view - ORACLE DATABASES

I want to ask you if there is a solution to auto-synchronize a table ,e.g., every one minute based on view created in oracle.
This view is using data from another table. I've created a trigger but I noticed a big slowness in database whenever a user update a column or insert a row.
Furthermore, I've tested to create a job schedule on the specified table (Which I wanted to be synchronized with the view), however we don't have the privilege to do this.
Is there any other way to keep data updated between the table and the view ?
PS : I'm using toad for oracle V 12.9.0.71
A materialized view in Oracle is a database object that contains the results of a query. They are local copies of data located remotely, or are used to create summary tables based on aggregations of a table's data. Materialized views, which store data based on remote tables, are also known as snapshots.
Example:
SQL> CREATE MATERIALIZED VIEW mv_emp_pk
REFRESH FAST START WITH SYSDATE
NEXT SYSDATE + 1/48
WITH PRIMARY KEY
AS SELECT * FROM emp#remote_db;
You can use cronjob or dbms_jobs to schedule a snapshot.

How incremental refresh on Materialized view works?

Say I have a below query which is constructing materialized view(MV)
select * from employee, department where employee.id = department.id and name like '%Andy%'
I have two related questions on How incremental update on MV works internally
1) Say I insert or update any entry either in employee or department table, can I configure increment refresh on MV to be asynchronous of insert/update transaction
or it is mandatory to be synchronous process ?
2)While insert or update , Does oracle evaluate(through transactionl logs) each updated/inserted row and apply the MV query criteria , see if satisfies it . If yes, update or insert the row in MV ?
1) Say I insert or update any entry either in employee or department table, can I configure increment refresh on MV to be asynchronous of insert/update transaction or it is mandatory to be synchronous process ?
If you want to have data available on a materialized view as soon as changes are committed on the base table then you can use ON COMMIT refresh method.
Or if you want to refresh by incrementally applying changes to the materialized view then you can use FAST refresh method. You can do this asynchronously.
2)While insert or update , Does oracle evaluate(through transactionl logas) each updated/inserted row and apply the MV query criteria , see if satisfies it . If yes, update or insert the row in MV ?
It depends upon what kind of refresh method you are using. If you are using FAST or ON COMMIT refresh method then yes, it only applies the changes to the MV which satisfy the criteria defined in the query used to create the MV.
For FAST REFRESH you have to create MATERIALIZED VIEW LOG on base tables you select for the MV. In these materialized view logs Oracle stores updated/inserted/deleted row information. i.e. Oracle does not use the REDO logs as you presumed.
Once all MViews based on your table are refreshed (either by ON COMMIT or manual REFRESH) content of according materialized view logs are truncated.

How to set different ways to delete in oracle, with and without activating a trigger

I'm using oracle 11g the schema follows as:
TRANSFER(id_transfer, origin_account, destine_account, amount, date, id_replica)
DELETES(id, table, id_replica, date)
Other tables, each have an id_replica as identifier.
I also have a trigger per table, when delete it copies the id_replica deleted in the table DELETES. So if I delete a transfer it first save into DELETES ( id, transfer, id_replica, sysdate), this is for having a record on what I deleted.
The problem is that now I want to make a delete without activating this trigger, I need to have 2 ways of deleting a row, activating the trigger and save what I delete into the table DELETES, and deleting the row without activating this trigger.
Some solutions that came to my mind:
making 2 different procedures/functions to delete a row en each table, (or just one with the trigger the other one can be done as normal).
enabling or disabling the trigger before each delete, this is kind of complicated because its done a lot of times
How do I make a procedure/function to delete a row? Is there other way to do this?

Is there a way to query the changes made by a materialized view fast refresh in Oracle?

Say that you have two Oracle databases, DB_A and DB_B. There is a table named TAB1 in DB_A with a materialized view log, and a materialized view named SNAP_TAB1 in DB_B created with
CREATE SNAPSHOT SNAP_TAB1
REFRESH FAST
AS SELECT * FROM TAB1#DB_A;
Is there a way to query in DB_B the changes made to SNAP_TAB1 after each call to fast-refresh the materialized view ?
DBMS_SNAPSHOT.REFRESH( 'SNAP_TAB1', 'F' );
In DB_A, prior to the refresh, you can query the materialized view log table, MLOG$_TAB1, to see which rows have been changed in TAB1. I'm looking for a way to query in DB_B, after each refresh, which rows have been refreshed in SNAP_TAB1.
Thanks!
I think the lines below work with prebuilt table:
You can add a column in the table SNAP_TAB1.
For inserts You can put it on default sysdate => for every insert you'll have the timestamp of the insert.
For updates you can use a trigger. Because the column is not involved in the Materialized View, updating the column with the trigger won't be a problem.
Probaly better, with the trigger you can use an unique id to store in that column, incremented before every new refresh.(Obtaining the unique id may have different aproaches.)
Obviously, you can't track deletes with this idea.

Resources