Merge statement: update only when a difference
HelloI have two tables have almost the same columns, how can I use the merge statement to update the table target only when there is difference between the source and target table. Is there an easier way to do not compare every column one by one? I use Oracle 11.2.
Here's the MERGE statement:
Merge into trgt tb_trgt using tb_src src
on (src.id = trgt.id)
When not matched then values of insertion (trgt.id, trgt.nm, trgt.addr) (src.id, src.nm, src.nm)
when matched, then update set trgt.nm = src.nm, trgt.addr = src.addr
where trgt.nm <>src.nm or trgt.addr <>src.addr
;
Is there an easier way to clarify the clause in the NO MATCHED? I don't want to compare every column in the tables. Because I might have a lot of columns in tables.
Thank you
939569 wrote:
I have two tables have almost the same columns, how can I use the merge statement to update the table target only when there is difference between the source and target table. Is there an easier way to do not compare every column one by one? I use Oracle 11.2.
Is there an easier way to clarify the clause in the NO MATCHED? I don't want to compare every column in the tables. Because I might have a lot of columns in tables.
I use the method of Tom Kyte to compare tables; It gives me the differences between the source and the target using GROUP BY, who manages the value NULL comparisons. Can I use this result in the MERGER. Here is a step by step illustration. First, set up test data:
define num_rows = 10
/
define pct = 20
/
define value_length = 50
/
define num_mods = round((&num_rows/3)*(&pct/100),0)
/
DROP TABLE T_TARGET;
/
DROP TABLE T_SOURCE;
/
create table t_target(key1 number, value1 varchar2(&value_length), constraint pk_target primary key(key1));
insert /*+ append */ into t_target
select level+&num_mods*3, rpad('DO NOTHING - same in source and target ',&value_length, '*')
from dual
where level <= &num_rows-&num_mods*2 connect by level <= &num_rows-&num_mods*2;
/
create table t_source as select * from t_target;
/
insert into t_source
select level, rpad('INSERT - in source, not in target ',&value_length, '*')
from dual where level <= &num_mods connect by level <= &num_mods;
/
insert into t_target
select level+&num_mods, rpad('DELETE (after update) - not in source, in target ',&value_length, '*')
from dual where level <= &num_mods connect by level <= &num_mods;
/
insert into t_source
select level+&num_mods*2, rpad('UPDATE - put this in target ',&value_length, '*')
from dual where level <= &num_mods connect by level <= &num_mods;
/
insert into t_target
select level+&num_mods*2, rpad('UPDATE - update this from source ',&value_length, '*')
from dual where level <= &num_mods connect by level <= &num_mods;
/
commit;
/
select 't_target', count(*), value1 from t_target group by 't_target', value1
union all
select 't_source', count(*), value1 from t_source group by 't_source', value1;
/
'T_TARGET' COUNT(*) VALUE1
---------- ---------- --------------------------------------------------
t_target 1 UPDATE - update this from source *****************
t_target 8 DO NOTHING - same in source and target ***********
t_target 1 DELETE (after update) - not in source, in target *
t_source 1 UPDATE - put this in target **********************
t_source 8 DO NOTHING - same in source and target ***********
t_source 1 INSERT - in source, not in target ****************
So, I need to do an insert, update, and a delete.
Now I'll build code comparison step by step. I don't show the results every time, but if you run each query yourself can see what is happening.
-- Step by step build of "refresh by merge" USING ROWIDs
-- Result: with cardinality hint, can use "BY USER ROWID" and avoid 3d full scan
-- 1) Full scan of both tables to get data,
-- identify old / new records and get old ROWID
select KEY1,VALUE1,
1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
UNION ALL
SELECT KEY1,VALUE1,
0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
/
-- 2) GROUP BY compares records, identical records have old_cnt = new_cnt
select KEY1,VALUE1,
sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
FROM (
select KEY1,VALUE1,
1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
UNION ALL
SELECT KEY1,VALUE1,
0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
)
group by KEY1,VALUE1
/
-- 3) Filter out identical records
select KEY1,VALUE1,
sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
FROM (
select KEY1,VALUE1,
1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
UNION ALL
SELECT KEY1,VALUE1,
0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
)
group by KEY1,VALUE1
having sum(old_cnt) <> sum(new_cnt)
/
-- 4) for INSERT, keep NEW; for DELETE, keep OLD;
-- for UPDATE, keep NEW values and OLD rid
SELECT /*+ cardinality(1) */ KEY1,VALUE1,
old_cnt, new_cnt, row_number() OVER(PARTITION BY KEY1 ORDER BY old_cnt) rn
, max(rid) over(partition by key1) rid
from (
select KEY1,VALUE1,
sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
FROM (
select KEY1,VALUE1,
1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
UNION ALL
SELECT KEY1,VALUE1,
0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
)
group by KEY1,VALUE1
having sum(old_cnt) <> sum(new_cnt)
)
/
-- 5) Filter out OLD UPDATE record, not needed
SELECT KEY1,VALUE1,
new_cnt, rid
FROM (
SELECT /*+ cardinality(1) */ KEY1,VALUE1,
old_cnt, new_cnt, row_number() OVER(PARTITION BY KEY1 ORDER BY old_cnt) rn
, max(rid) over(partition by key1) rid
from (
select KEY1,VALUE1,
sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
FROM (
select KEY1,VALUE1,
1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
UNION ALL
SELECT KEY1,VALUE1,
0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
)
group by KEY1,VALUE1
having sum(old_cnt) <> sum(new_cnt)
)
) where rn = 1
/
KEY1 VALUE1 NEW_CNT RID
1 INSERT - in source, not in target **************** 1
2 DELETE (after update) - not in source, in target * 0 AAAcDHAAMAAAACtAAA
3 UPDATE - put this in target ********************** 1 AAAcDHAAMAAAACtAAB
Now, here's the real MERGER:
merge into T_TARGET o
USING (
SELECT KEY1,VALUE1,
new_cnt, rid
FROM (
SELECT /*+ cardinality(1) */ KEY1,VALUE1,
old_cnt, new_cnt, row_number() OVER(PARTITION BY KEY1 ORDER BY old_cnt) rn
, max(rid) over(partition by key1) rid
from (
select KEY1,VALUE1,
sum(old_cnt) old_cnt, sum(new_cnt) new_cnt, max(rid) rid
FROM (
select KEY1,VALUE1,
1 old_cnt, 0 new_cnt, rowid rid from T_TARGET o
UNION ALL
SELECT KEY1,VALUE1,
0 old_cnt, 1 new_cnt, NULL FROM T_SOURCE n
)
group by KEY1,VALUE1
having sum(old_cnt) <> sum(new_cnt)
)
) where rn = 1
) n
on (o.rowid = n.rid)
when matched then update set
VALUE1=n.VALUE1
DELETE WHERE (n.new_cnt = 0)
WHEN NOT MATCHED THEN INSERT (
KEY1,VALUE1
) VALUES (
n.KEY1,n.VALUE1
)
/
Published by: stew Ashton on February 7, 2013 20:42
Tags: Database
Similar Questions
-
Hi Experts,
I write under the MERGE statement. In this cardinality of the table_a table_b is 1:2. That is, each record of table_b corresponds to 2 records in table_a based on columns in CLAUSE.
Well, this query throws below error.
-Error-
ORA-12801: error reported in the P011 parallel query server
ORA-30926: failed to get a stable set of rows in the source tables
However, the same statement runs successfully what tip PARALLEL is removed altogether. (There are no duplicates in table_b based on unity, group, loc columns.)
Please sugget if anything look his place here or causes possible.
-Request-
MERGE / * + PARALLEL (8) * /.
IN table_a a
With the HELP of table_b b
ON (a.unit = b.unit
AND a.group = b.group
AND a.loc = b.loc)
WHEN MATCHED
THEN UPDATE
SET a.u_pushonly = b.u_pushonly
a.u_seasonind = b.u_seasonind,
a.eff = BOX
WHEN b.u_season_start_dt <>TO_DATE('01/01/1970','DD/MM/YYYY')
OR b.u_season_end_dt <>TO_DATE('01/01/1970','DD/MM/YYYY')
OR b.u_pushonly = 1
THEN more GRAND (NVL (b.u_assortment_start_dt, TO_DATE('01/01/1970','DD/MM/YYYY'))
b.u_season_start_dt)
Of OTHER NVL (b.u_assortment_start_dt, TO_DATE('01/01/1970','DD/MM/YYYY'))
END;
kendenny wrote:
Fusion requires that columns be unique in both tables. Given that you only update was not insert is not put in correspondence, then you can use a single update statement.
I don't think so, it requires only NEW data is unique. Informal argument: a single line in the new table can update several lines in the table of old, but you can not use several lines in the new table to update a single row in the old table.
However, I wonder if something went wrong with the parallelism so that the lines with the same VALUES for the data (old) table_a has been distributed through many slaves, leading to several slaves, trying to update each on the other lines. (I don't see how this could happen, but it's one of the problems with bugs - if she should not deceive you, it can be difficult to imagine how it's bad).
To the OP - this sounds like something, you need to trigger an SR for (after a search of MOS).
Concerning
Jonathan Lewis
-
Firefox keeps advising me up-to-date even if a few Add ons are not compatible with the newer version. Although I don't want to be notified when an update is available, I won't update if the add ons are not compatible. Also, advising me update is useless because I will not refresh firefox when all add ons are not compatible.
Is it possible to put the automatic notification about the availability of updates to appear only when all add ons are compatible?
You can install this extension to see the information of current compatibility on the subject: addons page.
-
change should only be updated only when the value of lov
Hi experts Adf.
JDeveloper 11.1.1.4.0
I have a usecase where a lov and a field date is in a table. Each time, I have a lov selects for the first time, and then save the button. Then change date is get inserted with null. (it's fine).
Now when I change the existing value of the lov and then clicking on save, then the modified date is updated. (it is also very good).
Scenario question: suppose that in the first row, WE show dropdown because it is saved in the database and change date as null.
However when I try to change the value to lov ' sales and do not click Save. Now, once I select IT and clicking record. In this case, change date is updated.
Idle screenplay: Change Date must be updated if there is no modification.
If (operation == DML_UPDATE) {}
setModifyDate (newTimestamp (System.currentMillis));
}
You can check the value of publication and skip this step if postedValue is newValue.
See this example: http://adfcodebits.blogspot.com/2010/07/bit-22-using-getpostedattribute-to.html
Dario
-
Hi all
Since the 10g database, we can use MERGE statement without the WHEN MATCHED clause.
I am looking to ODI to generate that kind of statement, but without success because it allways gives error saying I need a column for update.
This kind of check/insert statement would be great in a model of Vault!
Can someone help me please?
Thank you very much!
Where is the error? In the designer when you try to run your interface or is the error of Oracle database and reported to the operator?
If its designer, better to keep some columns checked for updated to keep happy ODI and twist the revenge to handle this:
I suggest that create you an Option KM, something like "MERGE_UPDATE" - use a checkbox for the values True or False.
Then, in step of the IKM making the scarf of fusion WHEN matched part here an if / then like this:
<% if ( odiRef.getOption( "MERGE_UPDATE'" ).equals("1")) { %>
When matched...
< %="odiRef.getColList...">
<% } %>
Then deform the part of the merge statement code block you want to turn off in external th < %="" et="" %=""> in my example.
This will be part of the generated code depends on the KM Option so it can be flown by interface.
-
Hi all
I have a main table and a table of detail (the two are linked by a key (Param_id)).
I just need to know is possible so that we can insert a record into the child table, whenever we are inserting record to master through a Merge statement.
When matched
Update...
When not matched
Insert...
-An entry will be in the Master table, I want to know, is there a command by which I can make the entry in the child table, also
Is no excuse for a double wire display.
You have not 'right' to an answer. Respondents are volunteers who are free to choose what threads they meet.
If someone won't respond to your thread creates a new thread with the same question will not help.
And when someone mistreats forums by not following the guidelines of the forum makes it just AS likely that people will want to help you.
-
Person registering in the Merge statement error!
Is it possible to save indivudual error in the MERGE statement (Update / Insert).
I'm unable to save these error. instead of MERGING, if I update the table in the cursor loop then I am able to record the individual error but the process takes time.
Thanks in advance.
DebaHi Deba,
Logging of DML errors:
SQL> create table tab1 (x number(1)); Table created. SQL> exec dbms_errlog.create_error_log('tab1') PL/SQL procedure successfully completed. SQL> SQL> merge into tab1 t 2 using (select 1 x from dual union all 3 select 112 x from dual) s 4 on (t.x = s.x) 5 when not matched 6 then insert (x) values (s.x) 7 log errors into err$_tab1 reject limit unlimited; 1 row merged. SQL> SQL> COL x for 9999 SQL> select * from tab1; X ----- 1 SQL> COL x for a4 SQL> select ora_err_number$, X from err$_tab1; ORA_ERR_NUMBER$ X --------------- ---- 1438 112 SQL>
Concerning
Peter -
How to design a trigger to update only if a column value is changed?
Hello
I have a nice little trigger that updates the CARD table when the table is updated. This table is updated within a master/detail form. It's the main table.
Relaxation is used mainly to update the columns 'FICHE_MODIFIEE_PAR' (in English, it means "modified by") and "DATE_MODIFICATION" (in English, it means 'date modified'). I wish that these columns updates ONLY when the values in the columns 'TOTAL_HEURES' and 'TOTAL_HEURES_EXCEPTIONNELLES' are changed. These two columns have a default value for the number 0. That means that these columns change means change it value from the value 0 by default with another value or a value to another value. If the value of one or two of these two columns changes, the trigger must be fired for updating the column 'FICHE_MODIFIEE_PAR' and 'DATE_MODIFICATION '.
Thank you for your help.create or replace TRIGGER OBSERVATOIRE.TIB_FICHE before insert or update on OBSERVATOIRE.FICHE for each row begin if inserting and :new.fiche_id is null then select FICHE_SEQ.NEXTVAL INTO :new.FICHE_ID from dual; end if; if inserting then :new.fiche_cree_par := v('USER'); :new.date_creation := sysdate; end if; if updating then :new.fiche_modifiee_par := v('USER'); :new.date_modification := sysdate; end if; end;
ChristianHello Christian,.
You can reference and compare the old and new values. For example
IF: NEW. TOTAL_HEURES <> : OLD. TOTAL_HEURES OR: NEW. TOTAL_HEURES_EXCEPTIONNELLES <> : OLD. TOTAL_HEURES_EXCEPTIONNELLES
THEN
do your stuff
END IF;Greetings,
Roelhttp://roelhartman.blogspot.com/
http://www.bloggingaboutoracle.org/
http://www.Logica.com/ -
problems with wireless Vista "local only".
How is it that some machines running windows vista, when the router is updated or changed, they show "limited or local only" when you then reconnect wireless... nothing else was changed on those computers and other devices can connect ok?Hello
Each router is assigned to the specific address (called IP address or IP address). And each router maintains its own database (called as base of router) to follow the networking devices communicate with him. When the router is changed, the particular router is unable to detect the device, especially the network card to communicate with the computer. Since he does not have details of the database of network devices, communicate with him.
- You are able to access the Internet?
Try the steps mentioned below and check:
Method 1:
Step 1: Enable or disable a network adapter and then check:
http://Windows.Microsoft.com/en-CA/Windows-Vista/enable-or-disable-a-network-adapter
Step 2: Run Network Diagnostic tool and check:
Network connection issues: http://Windows.Microsoft.com/en-us/Windows-Vista/troubleshoot-network-connection-problems
Method 2: Wi - Fi and in Windows network connection issues:
Reference links:
Of network connectivity status incorrectly as 'Local' only on a Windows Server 2008 or Windows Vista-based: http://support.microsoft.com/kb/947041
Setting up a wireless network: http://Windows.Microsoft.com/en-us/Windows-Vista/setting-up-a-wireless-network
Connection to wireless with Windows Vista: http://technet.microsoft.com/en-us/library/bb878035.aspx
Hope it works.
-
I bought and downloaded Lightroom 6 Lightroom 5.7 update. When I go to install it says that it cannot install because it only works on 64-bit I did not. Is there a 32-bit version as there was in Lightroom 5
N ° 6 of Lightroom is 64-bit only.
-
Updates the update only changed columns statement?
Let's say I TABLE1 with columns ID (2.0), FNAME VARCHAR2 (20), LNAME VARCHAR2 (20), AGE NUMBER (2.0). I insert a new record:
INSERT INTO TABLE1 (ID, FNAME LNAME, AGE) VALUES (1, 'Steve', 'Jobs', 40);
so I say:
Setting a DAY TABLE1 SET FNAME = "Steve", LNAME = "Employment", AGE = 56 WHERE ID = 1;
As you see the value of AGE column is different, but in the UPDATE statement I always put other columns of values. I wonder if Oracle is smart enough to update only the AGE column or it will update all columns?I do not think that Oracle performs this check: it simply updates the specified such columns in the SQL statement.
Here is a 5 year old J. Lewis article that explains why Oracle works this way: http://jonathanlewis.wordpress.com/2007/01/02/superfluous-updates/.
-
Calling a function only when the State is active
I turn to find the event just to call a function only when the status is active. In fact, I created a State to display the 'product details' click and once the system changes to this State - I have to perform a function.
Here's the context:
Let's say that you are on the home page where you will need to click on a product to see details. By clicking on the product, the State to view the details of the product will be activated and a variable inside the new state you will receive all the data (from the class of product). But I discovered Flex run all States at the beginning and we need to watch how declare our function to make sure that we do not have a null to a variable/object reference. Given that value is moving to the State only when the click event to occur, the process of globalization, execution of all States at the beginning will not have any value yet (for the specific product to deal with in the State of the productDetails). So I can't use creationComplete to perform a simple function like setSpecs(), where all the values (for example, width, height, circumference, diameter, price, etc.) will be instiate specific labels.
What event to use to call a function internal once we are in the State? Just using the creationComplet and stated if he check the currentState = that I have to work on is not enough. I tried 'activate', 'show', 'enterStage' and many others, but without success. I tried to search the Internet, but it seems that this problem is not popular enough to generate sufficient results.
But I know that it is possible in the case otherwise it will be is not logical and since Flex work very well with the event, I found the right event. It's something basic I know, but when you do not know, it seems difficult to find! ;-))Thanks Greg!
I agree, this is a better method. So I'll change my SENSITIVITY to use viewStack instead of the State. But the problem persists what that, if we use the viewStack State to launch an event only when the State/viewStack is displayed on the screen.
I found something that works very well for me: updateComplete.
First of all, I found this before reading your information about viewStack so it worked very well for the method of the State. That I decided to do a test to viewStack and made the necessary changes to the code to reflect a viewStack navigation and make sure the updateComplete was not within my component (stateProduct.mxml). The system was not able to view the specification as the setSpecs() function was not instantiate when displayed. I added the updateComplete = "{setSpecs ()} ' and everything worked great!" So I conclude that no matter if you are using a viewStack State, the updateComplete event can be used to run or functions only when the component is displayed on the screen.
Now, I have to make my transition between the State working with viewStack effect! ;-))
Thanks to Greg for this useful tip!
-
insert/update County in the merge statement
In the Merge statement, we can count the number of inserted rows and updated?
ROWCOUNT SQL % simply returns the number of rows merged.
It does not tell us the separately the line inserted and updated.# To insert the rowcount is the number of inserted rows for update is the number of rows updated, for the merger, that's the number of merged lines.
-
VLD-2761: A corresponding column cannot be updated in a merge statement
Help!
I use OWB for the first time. I want to update and insertion of a table of SQL server (source), but I get a warning every time that I have valid mapping. I have the Type of loading as "UPDATE/INSERT" and matched on PK.
"VLD-2761: impossible to generate the Merge statement."
MERGE statement cannot be generated because the SCHDL_REFNO column is used for correspondence and updating.
A column cannot be updated in a merge statement.
I use the corresponding PK, but I need the PK inserted if it didn't come out.
Thank youI hope that you understand why it worked and how it works rather than make the suggested changes and move forward.
-
Return in the MERGE statement clause
Hello
I use Oracle 10 g Version
I tried the code using UPDATE with return Clause & MERGER with return below Clause.
I have not found ANY error while working with the UPDATE statement. Here is the code with the UPDATE statement
DECLARE TYPE empno_list IS TABLE OF emp.empno%TYPE; vempno_list empno_list; BEGIN UPDATE emp SET comm = 11 WHERE deptno IN (SELECT deptno FROM dept) RETURNING empno BULK COLLECT INTO vempno_list; FOR i IN vempno_list.FIRST .. vempno_list.LAST LOOP DBMS_OUTPUT.put_line ('Values of EMP ' || vempno_list (i)); END LOOP; END;
But PL/SQL error: ORA-00933: SQL not correctly completed command when you work with the MERGE statement
declare type empno_list is table of emp.empno%type; vempno_list empno_list; begin merge into emp tgt using dept src on (src.deptno =tgt.deptno) when matched then update set tgt.comm=12 returning tgt.empno bulk collect into vempno_list ; for i in vempno_list.first .. vempno_list.last loop dbms_output.put_line('Values of EMP '||vempno_list(i) ) ; end loop; end;
Please suggest me
Probably because BACK IN clause does not belong to the MERGE statement. It is available only for INSERT, UPDATE, and DELETE. Here's the quote from Oracle Documentation:
The static method
RETURNING
INTO
article belongs to aDELETE
,INSERT
, orUPDATE
statement. The dynamicRETURNING
INTO
article belongs to aEXECUTE
IMMEDIATE
statement.And here is the link.
It will be useful.
Ishan
Maybe you are looking for
-
Satellite L300 (PSLB8E) - Driver for Ethernet controller
Hello I just reinstalled Vista (my records of repair so so borrowed a Vista DVD of lost friends). I have installled the LAN driver (here) and can connect to the internet fine (via cable in any case, as I have no wireless). Anyway when I go into Devic
-
Image-but window Media Player no sound when I play a DVD
When I try to play DVD, there is picture, but no sound in my laptop. I received a message from windows media player is COOD1163. May be is one to help me with this. Moved from feedback Original title: Windows media player.
-
Acer recovery disks do not install Windows 7 on a new hard drive SSD
Hi all! I have Ace Aspire 5742 G laptop and I have problems to install the Windows 7 operating system on my new hard drive SSD (I bought the SSD because the original hard drive is defect and do all the time... blue screens) For the factory restore, I
-
HP pavilion g4 series laptop PC - can I switch the processor and graphics card?
I was wondering because I saw a lot of laptop users replacing or upgrading their laptop processor and video/graphics card, is it possible for me to upgrade mine? in fact, I would like to upgrade mine especially that my processor with a capacity of 2.
-
Very slow PC after installing xp sp3
I recently installed windows xp SP3 on my PC. Once all installed began to go very very slow. I ran avast antivirus, once disabled or uninstalled the PC worked fine, so I removed and replaced by AVG 2011. The same thing is happening again. It seems to