MERGE - When not matched INSERT's exception - sql

i have a PL/SQL procedure using MERGE :
MERGE INTO
table_dest d
USING
(SELECT * FROM my_Table) s
ON
(s.id = d.id)
when matched then UPDATE set d.col1 = s.col1
when not matched then INSERT (id, col1) values (s.id, s.col1);
now lets say the query s returns mutiple rows with same id wich will returns an ORA-00001: unique constrain error
what i want to do is to send the duplicated columns to another table my_Table_recyledbin to get a successful INSERT, can i use EXCEPTION WHEN DUP_VAL_ON_INDEX ? if yes how to use it with the MERGE statement?
Thanks in advance

Why not handle the archiving of duplicate rows to the recycle bin table in a separate statement?
Firstly, do your merge (aggregating the duplicate rows to avoid the unique constraint error). I've assumed a MAX aggregate function on col1, but you can use whatever suits your needs -- you have not specified how to decide which row to use when there are duplicates.
MERGE INTO
table_dest d
USING
(SELECT a.id, MAX(a.col1) as col1
FROM my_Table a
GROUP BY a.id) s
ON
(s.id = d.id)
WHEN MATCHED THEN UPDATE SET d.col1 = s.col1
WHEN NOT MATCHED THEN INSERT (id, col1) VALUES (s.id, s.col1);
Then, deal with the duplicate rows. I'm assuming that your recycle bin table does allow duplicate ids to be inserted:
INSERT INTO my_Table_recyledbin r (id, col1)
SELECT s.id, s.col1
FROM my_Table s
WHERE EXISTS (SELECT 1
FROM my_Table t
WHERE t.id = s.id
AND t.ROWID != s.ROWID)
Hopefully, that should fulfil your needs.

Can't you just use an error-logging clause? I.E., add this line at the end of your MERGE statement:
LOG ERRORS INTO my_Table_recycledbin

Related

How to rebuild this query using joins

help me please to understand, how to remake this query using joins.
INSERT INTO mytable
(user_id, tag)
SELECT ?, ?
WHERE NOT EXISTS (SELECT user_id FROM mytable WHERE user_id=? AND tag=?)
I saw similar questions that use two different tables, but here i have one table.
I need to insert only if the same entry does not exist. mytable table does not have any UNIQUE constraints and i can't change scheme.
You can put your parameters into a common table expression that is reusable:
with data (user_id, tag) as (
values (?,?)
)
INSERT INTO mytable (user_id, tag)
SELECT d.user_id, d.tag
FROM data d
WHERE NOT EXISTS (SELECT *
FROM mytable t
cross join data d
WHERE t.user_id = d.user_id
AND t.tag = d.tag)
Note that this will not prevent concurrent insert of the same values. The only way to achieve that is to add a unique constraint (and then you can use on conflict do nothing)

Inserting new rows in table if already not exisitng

I have a table than over time can get bigger and I want to insert some of its rows in another table but I also want to make sure I am not duplicating the rows that I had inserted before.
So here is the type of condition for my insert:
INSERT INTO SecondTable(Col1,Col2)
SELECT Col5,Col6
FROM
FirstTable ft
WHERE ft.RecType = 'ABC'
So if I keep running this it will keep inserting the same rows again and again. How can I tell it only insert if it is not already there?
You can use not exists:
INSERT INTO SecondTable(Col1,Col2)
SELECT Col5,Col6
FROM FirstTable ft
WHERE ft.RecType = 'ABC' AND
NOT EXISTS (SELECT 1 FROM SecondTable t2 WHERE t2.col1 = ft.col5 AND t2.col2 = ft.colt6);
Generate unique constraint on table with proper columns which identifies unicity. This will also help you to preserve integrity of your table. when you try to insert records into the RDBMS will give you an error.
ALTER TABLE SecondTable
ADD UNIQUE (col1, col2, col3);
INSERT INTO SecondTable(Col1,Col2)
SELECT Col5,Col6
FROM FirstTable ft
LEFT JOIN SecondTable st ON st.Col1 = ft.Col1
WHERE st.Col1 IS NULL AND ft.RecType = 'ABC'

SQL: How to insert/update multiple tables by checking duplicates in one table?

MS SQL: I want to insert/update data in a table based on below conditions.
I have tried using IF EXISTS as shown below. Can anyone correct me if I'm wrong here or send an alternative one which does this job better?
IF NOT EXISTS (select 1 from TableA where col1 in (select col1 from tableA))
BEGIN
INSERT INTO TableA
SELECT * FROM TableB
WHERE some condition
DELETE FROM TableB
WHERE some condition
DELETE l FROM TableC l
INNER JOIN #temptable s on l.col1 = s.col1 WHERE l.col1 = s.col1
END
ELSE
BEGIN
UPDATE TableA set (columns which are changed in TableA) where condition which pulls up exisiting query
END
Its very simple using new MERGE operator provide in sql server 2008.
In MERGE operation you can define source and target table and based on matching and un-matching rows you can perform delete , update or insert in one shot.
please refer below link for more detail - https://www.red-gate.com/simple-talk/sql/learn-sql-server/the-merge-statement-in-sql-server-2008/

Correct the update query for marking duplicate rows in DB2

I'm trying to update a column with the value 1 where the following criteria match.
UPDATE
(SELECT TBL.KEY, TBL.IS_DUPLICATE FROM MYTABLE AS TBL JOIN
(SELECT TBL1.KEY FROM MYTABLE AS TBL1 GROUP BY TBL1.KEY HAVING COUNT(TBL1.KEY)>1) SELECTION
ON SELECTION.KEY = TBL.KEY ORDER BY TBL.KEY ASC) OuterSelection
SET OuterSelection.IS_DUPLICATE = 1;
Here is the error I'm getting when running this query.
SQL Error [42807]: The target fullselect, view, typed table, materialized query table, range-clustered table, or staging table in the INSERT, DELETE, UPDATE, MERGE, or TRUNCATE statement is a target for which the requested operation is not permitted.. SQLCODE=-150, SQLSTATE=42807, DRIVER=4.16.53
Problem was that the selection had to be matched in the WHERE clause, and the UPDATE should just specify the table. Here is the solution:
UPDATE TBL
SET IS_DUPLICATE=1
WHERE KEY IN (SELECT KEY
FROM TBL
GROUP BY KEY
HAVING COUNT(*) > 1);

Error: ORA-30926: unable to get a stable set of rows in the source tables

I am getting the error : unable to get a stable set of rows in the source tables when I ran the below statement.
merge into table_1 c
using (select rep_nbr, T_nbr, SF from table_2) b
on (c.rep_id=b.rep_nbr)
when matched then
update set
c.T_ID =b.T_nbr,
c.SF=b.SF
when not matched then
insert(T_id, SF)
values(null, null);
When i put distinct before the rep_nbr
merge into table_1 c
using (select distinct rep_nbr,t_nbr,SF from table_2) b
on (c.rep_id=b.rep_nbr)
when matched then
update set
c.T_ID =b.T_nbr,
c.SF=b.SF
when not matched then
insert(T_id, SF)
values(null, null);
ORA-01400: cannot insert NULL into c.rep_id.
I don't want to populate c.rep_id, i just need them to match and then update those records that matched.
If I understood correctly, you don't need MERGE, just an UPDATE. Something like this should work:
UPDATE table_1 t1
SET t1.t_id = (SELECT DISTINCT t2.t_nbr FROM table_2 t2 WHERE t1.rep_id = t2.rep_nbr),
t1.sf = (SELECT DISTINCT t2.sf FROM table_2 t2 WHERE t1.rep_id = t2.rep_nbr),
WHERE t1.rep_id IN (SELECT rep_nbr FROM table_2)
But, however, in later versions of Oracle (from 10th or 11th) you can take out parts of merge, for example, take out WHEN NOT MATCHED part.
remove part "with not matched then"
merge into table_1 c
using (select distinct rep_nbr,t_nbr,SF from table_2) b
on (c.rep_id=b.rep_nbr)
when matched then
update set
c.T_ID =b.T_nbr,
c.SF=b.SF