If the record exists in target but doesn't exist in source, i need to delete it - sql

So, i have two tables, the target table and the source one. I need to delete the rows that exists in the target table, but doesn't exists in the source table.
And the code:
MERGE INTO (SELECT id_car_bk, car_brand_bk, car_type_bk, new_car
FROM car_catalog_backup) CB
USING (SELECT id_car, car_brand, car_type FROM car_catalog) C
ON (CB.id_car_bk = b.id_car)
WHEN NOT MATCHED THEN
INSERT
(CB.id_car_bk, CB.car_brand_bk, CB.car_type_bk)
VALUES
(C.id_car, C.car_brand, C.car_type)
WHEN MATCHED THEN
UPDATE SET CB.car_brand_bk = C.car_brand;

You can use
DELETE car_catalog_backup b
WHERE not exists
( SELECT 0
FROM car_catalog c
WHERE b.id_car_bk = c.id_car );
or
DELETE car_catalog_backup b
WHERE b.id_car_bk not in
( SELECT c.id_car
FROM car_catalog c );
assuming car_catalog is the source, and car_catalog_backup is the target. The First one is preferable, since it's more performant.
If your aim is to find out with a MERGE statement similar to your case, then use the following
MERGE INTO car_catalog_backup a
USING (SELECT id_car, car_brand, car_type, car_brand_bk
FROM car_catalog
JOIN car_catalog_backup
ON id_car_bk = id_car
) b
ON (a.id_car_bk = b.id_car)
WHEN MATCHED THEN
UPDATE SET a.new_car = 1
DELETE
WHERE a.car_brand_bk != b.car_brand
WHEN NOT MATCHED THEN
INSERT
(id_car_bk, car_brand_bk, car_type_bk)
VALUES
(b.id_car, b.car_brand, b.car_type)
to delete the records matched for id columns ( a.id_car_bk = b.id_car ) but not matched for brand code columns ( a.car_brand_bk != car_brand ) as an example.
Demo

Delete from target
Where not exists
(
Select 1
From source
Where join of source and target
)

With a left join:
DELETE target
FROM target LEFT JOIN source
ON target.someid = source.otherid
WHERE source.otherid IS NULL;

Related

Update multiple columns with Joining 2 tables in SQL

Below is the code I am using for the update. The matching records between SRC and LKP table on the below condition are 31. But when I run the below update statement it's updating 200 records.Could you please suggest where could be the issue
UPDATE SRC src
SET (src.A,src.B,src.C,src.D) = (select lkp.A,lkp.B,lkp.C,'1'
from LKP lkp
inner join SRC
ON src.id_1=lkp.id_1
and src.CC=lkp.CC)
You have two issues:
You have no WHERE clause so all columns are updated.
You are referencing SRC in the subquery.
What I'm guessing you want is:
UPDATE SRC src
SET (src.A, src.B, src.C, src.D) =
(select lkp.A, lkp.B, lkp.C, '1'
from LKP lkp
where src.id_1 = lkp.id_1 and src.CC = lkp.CC
)
WHERE EXISTS (select 1
from LKP lkp
where src.id_1 = lkp.id_1 and src.CC = lkp.CC
);
For performance, you want in index on LKP(id_1, cc).

How to use Merge Command in Oracle

I have query operation like below. How can I write single merge query where DWB_ACCT_CLSS_STG2 is stage table and DWB_ACCT_CLASS is the target table?
INSERT INTO DWB_ACCT_CLSS_STG2
SELECT
STG1.ACCT_CLSS_CD
,STG1.ACCT_CLSS_NME
,STG1.ACCT_CLSS_DSC
,STG1.PROCESS_NAME
,STG1.EXECUTION_ID
,STG1.FILE_ID
,STG1.FILE_DATE
,STG1.DATA_DATE
,STG1.LOAD_USER
,STG1.LOAD_DATE
,STG1.DW_LAST_UPDATE_TIME
FROM DWB_ACCT_CLSS_STG1 STG1
LEFT OUTER JOIN DWB_ACCT_CLASS TRGT
ON STG1.ACCT_TYP_CD = TRGT.ACCT_TYP_CD
WHERE TRGT.ACCT_TYP_CD IS NULL;
INSERT INTO DWB_ACCT_TYP_STG2
SELECT
STG1.ACCT_TYP_CD
,STG1.ACCT_TYP_DSC
,STG1.PROCESS_NAME
,STG1.EXECUTION_ID
,STG1.FILE_ID
,STG1.FILE_DATE
,STG1.DATA_DATE
,STG1.LOAD_USER
,STG1.LOAD_DATE
,STG1.DW_LAST_UPDATE_TIME
FROM DWB_ACCT_CLASS_STG1 STG1
INNER JOIN DWB_ACCT_CLASS TRGT
ON STG1.ACCT_TYP_CD = TRGT.ACCT_TYP_CD
WHERE (
STG1.ACCT_TYP_DSC <> TRGT.ACCT_TYP_DSC
);
DELETE FROM DWB_ACCT_class WHERE (ACCT_TYP_CD) IN (SELECT ACCT_TYP_CD FROM DWB_ACCT_CLASS_STG2 STG2);
INSERT INTO DWB_ACCT_CLASS SELECT * FROM DWB_ACCT_CLASS_STG2;
I think you don't even need staging table DWB_ACCT_CLSS_STG2. You can use the following MERGE command:
MERGE INTO DWB_ACCT_CLASS TRGT
USING (SELECT STG1.ACCT_CLSS_CD,
STG1.ACCT_CLSS_NME,
STG1.ACCT_CLSS_DSC,
STG1.PROCESS_NAME,
STG1.EXECUTION_ID,
STG1.FILE_ID,
STG1.FILE_DATE,
STG1.DATA_DATE,
STG1.LOAD_USER,
STG1.LOAD_DATE,
STG1.DW_LAST_UPDATE_TIME
FROM DWB_ACCT_CLSS_STG1 STG1) STG1
ON (STG1.ACCT_TYP_CD = TRGT.ACCT_TYP_CD
AND STG1.ACCT_TYP_DSC <> TRGT.ACCT_TYP_DSC)
WHEN MATCHED THEN
UPDATE SET TRGT.ACCT_CLSS_CD = STG1.ACCT_CLSS_CD, ..... -- EXCEPT ACCT_TYP_CD AND ACCT_TYP_DSC COLUMN
WHEN NOT MATCHED THEN
INSERT (... COLUMNS OF THE DWB_ACCT_CLASS TABLE ....)
VALUES (STG1.ACCT_CLSS_CD,STG1.ACCT_CLSS_NME,.....STG1.DW_LAST_UPDATE_TIME) -- ORDER MUST MATCH WITH THE INSERT CLASUE COLUMN LIST

How to solve this SQL specific merge problem

How to solve the error:
The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.
merge CARD_ALERTS as t
using #tblAlerts as s
on (t.Id = s.AlertId and t.CardId = s.CardId)
when not matched by target
then insert(Id, ExternalCodeHolder, CardId, IsCardOwner, IBAN, PAN, MinAmount, Currency, ByEmail, BySMS, IssueDate, IsActive)
values(s.AlertId, s.ExternalCodeHolder, s.CardId, s.IsCardOwner, s.IBAN, s.PAN, s.MinAmount, s.Currency, s.ByEmail, s.BySMS, getdate(), 1)
when matched
then update set t.ByEmail = s.ByEmail, t.BySMS = s.BySMS, IsActive = 1, t.MinAmount = s.MinAmount
when not matched by source and t.Id=#AlertId
then update set t.IsActive = 3
As explained in the error message and in the comments, multiple rows of the source table correspond to the same row in the target one.
This will show you which rows of the target table have multiple rows from the source table that try to update them:
select t.Id,t.CardId,count(*) as [count]
from CARD_ALERTS as t
inner join #tblAlerts as s
on (t.Id = s.AlertId and t.CardId = s.CardId)
group by t.Id,t.CardId
having count(*)>1
This will also show you the multiple rows of the source table:
select t.*,s.*
from CARD_ALERTS as t
inner join #tblAlerts as s on (t.Id = s.AlertId and t.CardId = s.CardId)
inner join
(
select ca.Id,ca.CardId
from CARD_ALERTS as ca
inner join #tblAlerts as s
on (ca.Id = s.AlertId and ca.CardId = s.CardId)
group by ca.Id,ca.CardId
having count(*)>1
)tkey on t.Id=tkey.Id and t.CardId=tkey.CardId

With exists vs without exists in oracle

How would my output change if I remove exists statement from the following query.
UPDATE AR_CRDT C
set (OPERATOR_ID,UPDT_TS) = ( SELECT AD.OPERATOR_ID,sysdate
FROM
(
Select A.*
FROM AR1_CUSTOMER_CREDIT A
)AD
WHERE AD.CREDIT_ID = C.CRDT_ID
)
where exists ( SELECT 1
FROM
(
Select A.*
FROM AR1_CUSTOMER_CREDIT A
)AD
WHERE AD.CREDIT_ID = C.CRDT_ID
);
If you remove the exists, then OPERATOR_ID and UPDT_TS would be set to NULL for rows where the conditions do not match.
Why would you write this with the extra subqueries?
UPDATE AR_CRDT C
SET (OPERATOR_ID, UPDT_TS) = (SELECT AD.OPERATOR_ID, sysdate
FROM AR1_CUSTOMER_CREDIT A
WHERE A.CREDIT_ID = C.CRDT_ID
)
WHERE EXISTS (SELECT 1
FROM AR1_CUSTOMER_CREDIT A
WHERE A.CREDIT_ID = C.CRDT_ID
);
The EXISTS currently causes the updates to AR_CRDT to be limited to those records where the AR_CRDT record is associated with an AR1_CUSTOMER_CREDIT record.
Removing that clause will mean that ALL records of AR_CRDT will be updated. Some will have values for the sub-query and some will be NULL where there is no link between AR_CRDT and AR1_CUSTOMER_CREDIT.

UPDATE row when matching row exists in another table

I need to update a field on a table to be true only if a matching row exists in another table, for all the rows where the column is currently null in the main table.
This is a description of what I want to achieve:
UPDATE [LenqReloaded].[dbo].[Enquiry] A
SET [ResponseLetterSent] = 1
WHERE [ResponseLetterSent] IS NULL
AND EXISTS
(
SELECT * FROM [LenqReloaded].[dbo].[Attachment] B
WHERE A.[EnquiryID] = B.[EnquiryID]
)
This isn't syntactically correct.
I can't code it via an IF EXISTS... statement because I don't have the [EnquiryID] without reading the data from the table.
How should I format my UPDATE statement?
You weren't far off...
UPDATE A
SET A.[ResponseLetterSent] = 1
FROM [LenqReloaded].[dbo].[Enquiry] A
WHERE A.[ResponseLetterSent] IS NULL
AND EXISTS ( SELECT * FROM [LenqReloaded].[dbo].[Attachment] B WHERE A.[EnquiryID] = B.[EnquiryID] )
You need to use a join in your update:
UPDATE [LenqReloaded].[dbo].[Enquiry] SET [ResponseLetterSent] = 1
FROM [LenqReloaded].[dbo].[Enquiry] A
join [LenqReloaded].[dbo].[Attachment] B on A.[EnquiryID] = B.[EnquiryID]
WHERE A.[ResponseLetterSent] IS NULL
This seems counterintuitive, but you need to establish a table alias in a From clause but use that alias in the Update Clause...
Update E Set
ResponseLetterSent = 1
From LenqReloaded.dbo.Enquiry E
Where ResponseLetterSent Is Null
And Exists (Select * From LenqReloaded.dbo.Attachment
Where EnquiryID = E.EnquiryID)
The thing you are missing is the 'from' clause, which is a t-sql extension - it is the only way to assign an alias to the updated table
update [lenqreloaded].[dbo].[enquiry]
set [responselettersent] = 1
from [lenqreloaded].[dbo].[enquiry] a
where [responselettersent] is null
and exists (
select *
from [lenqreloaded].[dbo].[attachment] b
where a.[enquiryid] = b.[enquiryid]
)