{"id":11564,"date":"2022-07-31T13:07:32","date_gmt":"2022-07-31T11:07:32","guid":{"rendered":"https:\/\/www.salvis.com\/blog\/?p=11564"},"modified":"2023-11-08T16:58:47","modified_gmt":"2023-11-08T15:58:47","slug":"deleting-rows-with-merge","status":"publish","type":"post","link":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/","title":{"rendered":"Deleting Rows With Merge"},"content":{"rendered":"\n<p>The <code>merge<\/code> statement allows you to insert, update and delete rows in the target table in one go. This is great. However, the delete part does not work as expected. Is it a bug? No, it works exactly as documented. Nonetheless, I was not aware of this for years. Let&#8217;s take a look at this with an example.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setup<\/h2>\n\n\n\n<p>We create a table <code>t<\/code> (target) with three rows and a table <code>s<\/code> (source) with 4 rows. To log DML events we create some after row triggers on table <code>t<\/code>.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Setup<\/span><span role=\"button\" tabindex=\"0\" data-code=\"create table t (\n   id integer      not null primary key,\n   c1 varchar2(20) not null\n);\n\ninsert into t values (1, 'original 1');\ninsert into t values (2, 'original 2');\ninsert into t values (3, 'original 3');\n\ncreate table s (\n   id integer      not null,\n   op varchar2(1)  not null check (op in ('I', 'U', 'D')),\n   c1 varchar2(20) not null\n);\n\ninsert into s values (1, 'U', 'original 1');\ninsert into s values (2, 'U', 'changed 2');\ninsert into s values (3, 'D', 'deleted 3');\ninsert into s values (4, 'I', 'new 4');\n\ncreate or replace trigger t_ar_i after insert on t for each row\nbegin\n   sys.dbms_output.put_line('inserted id ' || :new.id);\nend;\n\/\n\ncreate or replace trigger t_ar_u after update on t for each row\nbegin\n   sys.dbms_output.put_line('updated id ' || :old.id);\nend;\n\/\n\ncreate or replace trigger t_ar_d after delete on t for each row\nbegin\n   sys.dbms_output.put_line('deleted id ' || :old.id);\nend;\n\/\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">create<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">t<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   id <\/span><span style=\"color: #569CD6\">integer<\/span><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">not null<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">primary key<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   c1 <\/span><span style=\"color: #569CD6\">varchar2<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">20<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">not null<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">insert into<\/span><span style=\"color: #D4D4D4\"> t <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;original 1&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">insert into<\/span><span style=\"color: #D4D4D4\"> t <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;original 2&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">insert into<\/span><span style=\"color: #D4D4D4\"> t <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;original 3&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">create<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">s<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   id <\/span><span style=\"color: #569CD6\">integer<\/span><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">not null<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   op <\/span><span style=\"color: #569CD6\">varchar2<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)  <\/span><span style=\"color: #569CD6\">not null<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">check<\/span><span style=\"color: #D4D4D4\"> (op <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #CE9178\">&#39;I&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;U&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;D&#39;<\/span><span style=\"color: #D4D4D4\">)),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   c1 <\/span><span style=\"color: #569CD6\">varchar2<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">20<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">not null<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">insert into<\/span><span style=\"color: #D4D4D4\"> s <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;U&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;original 1&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">insert into<\/span><span style=\"color: #D4D4D4\"> s <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;U&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;changed 2&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">insert into<\/span><span style=\"color: #D4D4D4\"> s <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;D&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;deleted 3&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">insert into<\/span><span style=\"color: #D4D4D4\"> s <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;I&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;new 4&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">create or replace<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">trigger<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">t_ar_i<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">after<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">insert<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> t <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> each <\/span><span style=\"color: #569CD6\">row<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">begin<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   sys.dbms_output.put_line(<\/span><span style=\"color: #CE9178\">&#39;inserted id &#39;<\/span><span style=\"color: #D4D4D4\"> || :new.id);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">end<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">create or replace<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">trigger<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">t_ar_u<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">after<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">update<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> t <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> each <\/span><span style=\"color: #569CD6\">row<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">begin<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   sys.dbms_output.put_line(<\/span><span style=\"color: #CE9178\">&#39;updated id &#39;<\/span><span style=\"color: #D4D4D4\"> || :old.id);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">end<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">create or replace<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">trigger<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">t_ar_d<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">after<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">delete<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> t <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> each <\/span><span style=\"color: #569CD6\">row<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">begin<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   sys.dbms_output.put_line(<\/span><span style=\"color: #CE9178\">&#39;deleted id &#39;<\/span><span style=\"color: #D4D4D4\"> || :old.id);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">end<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Insert, Update, Delete via Merge<\/h2>\n\n\n\n<p>Now, we can run this script:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Merge #1<\/span><span role=\"button\" tabindex=\"0\" data-code=\"set serveroutput on size unlimited\nmerge into t\nusing s\n   on (t.id = s.id)\n when matched then\n      update\n         set t.c1 = s.c1\n      delete\n       where op = 'D'\n when not matched then\n      insert (t.id, t.c1)\n      values (s.id, s.c1);\nselect * from t;      \nrollback;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> serveroutput <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">size<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">unlimited<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">merge<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">into<\/span><span style=\"color: #D4D4D4\"> t<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">using<\/span><span style=\"color: #D4D4D4\"> s<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> (t.id = s.id)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">when<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">matched<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">update<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         <\/span><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> t.c1 = s.c1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">delete<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> op = <\/span><span style=\"color: #CE9178\">&#39;D&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">when<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">not<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">matched<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">insert<\/span><span style=\"color: #D4D4D4\"> (t.id, t.c1)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (s.id, s.c1);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> t;      <\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">rollback<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Output of Merge #1<\/span><span role=\"button\" tabindex=\"0\" data-code=\"updated id 1\nupdated id 2\nupdated id 3\ndeleted id 3\ninserted id 4\n\n4 rows merged.\n\n        ID C1                  \n---------- --------------------\n         1 original 1          \n         2 changed 2           \n         4 new 4               \n\nRollback complete.\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">updated id 1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">updated id 2<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">updated id 3<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">deleted id 3<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">inserted id 4<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">4 rows merged.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        ID C1                  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- --------------------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 original 1          <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         2 changed 2           <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4 new 4               <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Rollback complete.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The merge statement applied the insert, update and delete operation in the target table <code>t<\/code>. The result in table <code>t<\/code> is what we expect.<\/p>\n\n\n\n<p>However, when I look at the output of the DML triggers I do not like the following things:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The row with <code>id<\/code> 1 was updated, even if the column <code>c1<\/code> did not change. This update is unnecessary and should be avoided, right?<\/li>\n\n\n\n<li>The row with <code>id<\/code> 3 was updated and then deleted. Updating a row and then deleting it? The first update does not seem necessary, right?<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Update Filter<\/h2>\n\n\n\n<p>The <code>merge_update_clause<\/code> documents an optional <code>where_clause<\/code> for the update part of a <code>merge<\/code> statement.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge_update_clause.gif\"><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" width=\"574\" height=\"159\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge_update_clause.gif\" alt=\"\" class=\"wp-image-11617\"\/><\/a><\/figure>\n\n\n\n<p>Let&#8217;s try that to avoid the unnecessary updates.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Merge #2<\/span><span role=\"button\" tabindex=\"0\" data-code=\"set serveroutput on size unlimited\nmerge into t\nusing s\n   on (t.id = s.id)\n when matched then\n      update\n         set t.c1 = s.c1\n       where op = 'U'\n         and t.c1 != s.c1\n      delete\n       where op = 'D'\n when not matched then\n      insert (t.id, t.c1)\n      values (s.id, s.c1);\nselect * from t;      \nrollback;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> serveroutput <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">size<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">unlimited<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">merge<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">into<\/span><span style=\"color: #D4D4D4\"> t<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">using<\/span><span style=\"color: #D4D4D4\"> s<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> (t.id = s.id)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">when<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">matched<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">update<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         <\/span><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> t.c1 = s.c1<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> op = <\/span><span style=\"color: #CE9178\">&#39;U&#39;<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">         <\/span><span style=\"color: #569CD6\">and<\/span><span style=\"color: #D4D4D4\"> t.c1 != s.c1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">delete<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> op = <\/span><span style=\"color: #CE9178\">&#39;D&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">when<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">not<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">matched<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">insert<\/span><span style=\"color: #D4D4D4\"> (t.id, t.c1)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (s.id, s.c1);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> t;      <\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">rollback<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Output of Merge #2<\/span><span role=\"button\" tabindex=\"0\" data-code=\"updated id 2\ninserted id 4\n\n2 rows merged.\n\n        ID C1                  \n---------- --------------------\n         1 original 1          \n         2 changed 2           \n         3 original 3          \n         4 new 4               \n\nRollback complete.\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">updated id 2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">inserted id 4<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">2 rows merged.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        ID C1                  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- --------------------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 original 1          <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         2 changed 2           <\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">         3 original 3          <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4 new 4               <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Rollback complete.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Good, no more unnecessary updates. But now we have a new issue. The row with <code>id<\/code> 3 is not deleted. It looks like the delete part of the <code>merge<\/code> statement is ignored.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Fine Print<\/h2>\n\n\n\n<p>I thought this was a bug and opened a service request some days ago. The friendly and patient support engineer directed me to this excerpt of the <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/19\/sqlrf\/MERGE.html#GUID-5692CCB7-24D9-4C0E-81A7-A22436DC968F__GUID-96879CD5-E50E-4D56-9A61-4974B1FBC679\">merge_update_clause<\/a> in the SQL Language Reference of the Oracle Database 19c:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Specify the <code>DELETE where_clause<\/code> to clean up data in a table while populating or updating it. <span class=\"highlight highlight-\" style=\"background-color:Lemonchiffon;color:black;\">The only rows affected by this clause are those rows in the destination table that are updated by the merge operation.<\/span>\n<\/p>\n<\/blockquote>\n\n\n\n<p>So, clearly not a bug.\u00a0The second sentence can be visualized as a Venn diagram:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes.png\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-300x300.png\" alt=\"Venn diagram of deletes in a merge statement\" class=\"wp-image-11624\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-300x300.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-1020x1024.png 1020w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-150x150.png 150w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-768x771.png 768w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-145x146.png 145w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-50x50.png 50w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-75x75.png 75w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-85x85.png 85w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-80x80.png 80w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-1x1.png 1w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes.png 1301w\" sizes=\"auto, (max-width:767px) 300px, 300px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">First Update Then Delete<\/h2>\n\n\n\n<p>So we have learned that we must first update a row before we can delete it when we use a <code>merge<\/code> statement. However, we can still avoid unnecessary updates if the row does not need to be deleted.<\/p>\n\n\n\n<p>Let&#8217;s update our script once more:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Merge #3<\/span><span role=\"button\" tabindex=\"0\" data-code=\"set serveroutput on size unlimited\nmerge into t\nusing s\n   on (t.id = s.id)\n when matched then\n      update\n         set t.c1 = s.c1\n       where t.c1 != s.c1\n          or op = 'D'\n      delete\n       where op = 'D'\n when not matched then\n      insert (t.id, t.c1)\n      values (s.id, s.c1);\nselect * from t;\nrollback;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> serveroutput <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">size<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">unlimited<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">merge<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">into<\/span><span style=\"color: #D4D4D4\"> t<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">using<\/span><span style=\"color: #D4D4D4\"> s<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> (t.id = s.id)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">when<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">matched<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">update<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         <\/span><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> t.c1 = s.c1<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> t.c1 != s.c1<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #569CD6\">or<\/span><span style=\"color: #D4D4D4\"> op = <\/span><span style=\"color: #CE9178\">&#39;D&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">delete<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> op = <\/span><span style=\"color: #CE9178\">&#39;D&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">when<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">not<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">matched<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">insert<\/span><span style=\"color: #D4D4D4\"> (t.id, t.c1)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (s.id, s.c1);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> t;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">rollback<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Output of Merge #3<\/span><span role=\"button\" tabindex=\"0\" data-code=\"updated id 2\nupdated id 3\ndeleted id 3\ninserted id 4\n\n3 rows merged.\n\n        ID C1                  \n---------- --------------------\n         1 original 1          \n         2 changed 2           \n         4 new 4               \n\nRollback complete.\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">updated id 2<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">updated id 3<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">deleted id 3<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">inserted id 4<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">3 rows merged.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        ID C1                  <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">---------- --------------------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         1 original 1          <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         2 changed 2           <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         4 new 4               <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Rollback complete.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Looks good!<\/p>\n\n\n\n<p>The update of the row with <code>id<\/code> 1 was suppressed because the <code>c1<\/code> column did not change. The row with <code>id<\/code> 2 was changed, a new row with <code>id<\/code> 4 was inserted and the row with <code>id<\/code> 3 is gone. We just have to live with the prior update of <code>id<\/code> 3.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>I imagine I&#8217;m not the only one who would have expected the <code>merge<\/code> statement to behave differently. Especially after watching <a href=\"https:\/\/asktom.oracle.com\/pls\/apex\/f?p=100:551::::551:P551_CLASS_ID:17904\">How to UPSERT (INSERT or UPDATE) rows with MERGE in Oracle Database<\/a> by Chris Saxon. He also mentioned &#8220;delete&#8221; <a href=\"https:\/\/www.youtube.com\/watch?v=NnonGaHGsdk&amp;t=2473s\">here<\/a> and <a href=\"https:\/\/www.youtube.com\/watch?v=NnonGaHGsdk&amp;t=2999s\">here<\/a>.<\/p>\n\n\n\n<p>Remember:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Delete only processes rows that were updated.<br \/>&#8212; Chris Saxon<\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>The merge statement allows you to insert, update and delete rows in the target table in one go. This is great. However, the delete part does not work as expected. Is it a bug? No, it works exactly as documented. Nonetheless, I was not aware of this for years. Let&#8217;s take a<span class=\"excerpt-hellip\"> [\u2026]<\/span><\/p>\n","protected":false},"author":1,"featured_media":11632,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[85],"class_list":["post-11564","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle","tag-sql"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Deleting Rows With Merge - Philipp Salvisberg&#039;s Blog<\/title>\n<meta name=\"description\" content=\"You can insert, update and delete rows with the merge statement in one go. This is great. However, the delete part does not work as expected. Is it a bug? No, it works exactly as documented.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Deleting Rows With Merge - Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"You can insert, update and delete rows with the merge statement in one go. This is great. However, the delete part does not work as expected. Is it a bug? No, it works exactly as documented.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/\" \/>\n<meta property=\"og:site_name\" content=\"Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-07-31T11:07:32+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-08T15:58:47+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-featured-1024x768.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"768\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Philipp Salvisberg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:site\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Philipp Salvisberg\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/\"},\"author\":{\"name\":\"Philipp Salvisberg\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"headline\":\"Deleting Rows With Merge\",\"datePublished\":\"2022-07-31T11:07:32+00:00\",\"dateModified\":\"2023-11-08T15:58:47+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/\"},\"wordCount\":492,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/merge-updates-deletes-featured.png\",\"keywords\":[\"SQL\"],\"articleSection\":[\"Oracle\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/\",\"name\":\"Deleting Rows With Merge - Philipp Salvisberg&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/merge-updates-deletes-featured.png\",\"datePublished\":\"2022-07-31T11:07:32+00:00\",\"dateModified\":\"2023-11-08T15:58:47+00:00\",\"description\":\"You can insert, update and delete rows with the merge statement in one go. This is great. However, the delete part does not work as expected. Is it a bug? No, it works exactly as documented.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/merge-updates-deletes-featured.png\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/merge-updates-deletes-featured.png\",\"width\":10155,\"height\":7615,\"caption\":\"Venn diagram of deletes in a merge statement\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2022\\\/07\\\/31\\\/deleting-rows-with-merge\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Deleting Rows With Merge\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\",\"name\":\"Philipp Salvisberg&#039;s Blog\",\"description\":\"Database-centric development\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\",\"name\":\"Philipp Salvisberg\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"width\":400,\"height\":400,\"caption\":\"Philipp Salvisberg\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\"},\"sameAs\":[\"http:\\\/\\\/www.salvis.com\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Deleting Rows With Merge - Philipp Salvisberg&#039;s Blog","description":"You can insert, update and delete rows with the merge statement in one go. This is great. However, the delete part does not work as expected. Is it a bug? No, it works exactly as documented.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/","og_locale":"en_US","og_type":"article","og_title":"Deleting Rows With Merge - Philipp Salvisberg&#039;s Blog","og_description":"You can insert, update and delete rows with the merge statement in one go. This is great. However, the delete part does not work as expected. Is it a bug? No, it works exactly as documented.","og_url":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/","og_site_name":"Philipp Salvisberg&#039;s Blog","article_published_time":"2022-07-31T11:07:32+00:00","article_modified_time":"2023-11-08T15:58:47+00:00","og_image":[{"width":1024,"height":768,"url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-featured-1024x768.png","type":"image\/png"}],"author":"Philipp Salvisberg","twitter_card":"summary_large_image","twitter_creator":"@phsalvisberg","twitter_site":"@phsalvisberg","twitter_misc":{"Written by":"Philipp Salvisberg","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/#article","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/"},"author":{"name":"Philipp Salvisberg","@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"headline":"Deleting Rows With Merge","datePublished":"2022-07-31T11:07:32+00:00","dateModified":"2023-11-08T15:58:47+00:00","mainEntityOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/"},"wordCount":492,"commentCount":1,"publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-featured.png","keywords":["SQL"],"articleSection":["Oracle"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/","url":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/","name":"Deleting Rows With Merge - Philipp Salvisberg&#039;s Blog","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/#primaryimage"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-featured.png","datePublished":"2022-07-31T11:07:32+00:00","dateModified":"2023-11-08T15:58:47+00:00","description":"You can insert, update and delete rows with the merge statement in one go. This is great. However, the delete part does not work as expected. Is it a bug? No, it works exactly as documented.","breadcrumb":{"@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/#primaryimage","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-featured.png","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2022\/07\/merge-updates-deletes-featured.png","width":10155,"height":7615,"caption":"Venn diagram of deletes in a merge statement"},{"@type":"BreadcrumbList","@id":"https:\/\/www.salvis.com\/blog\/2022\/07\/31\/deleting-rows-with-merge\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.salvis.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Deleting Rows With Merge"}]},{"@type":"WebSite","@id":"https:\/\/www.salvis.com\/blog\/#website","url":"https:\/\/www.salvis.com\/blog\/","name":"Philipp Salvisberg&#039;s Blog","description":"Database-centric development","publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.salvis.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515","name":"Philipp Salvisberg","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","width":400,"height":400,"caption":"Philipp Salvisberg"},"logo":{"@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg"},"sameAs":["http:\/\/www.salvis.com\/"]}]}},"_links":{"self":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/11564","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/comments?post=11564"}],"version-history":[{"count":26,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/11564\/revisions"}],"predecessor-version":[{"id":12722,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/11564\/revisions\/12722"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media\/11632"}],"wp:attachment":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media?parent=11564"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/categories?post=11564"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/tags?post=11564"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}