How to copy or update from one table to another table - sql

I have two tables. user and user_new
the user contains the old data.
the user_new contains the new data.
I want to sync the user_new to user.
if the data exist in user_new and not exist in user,then insert to user.
if the data exist in user and user_new, then update.(compare with the column id)
what's the fast sql to do it?

This works on any server version -
-- 1) Insert new record
INSERT INTO old_table(id, column)
SELECT n.id, n.column
FROM new_table n
LEFT JOIN old_table o ON n.id = o.id
WHERE o.id IS NULL
-- 2) Update existed record
UPDATE o
SET column = n.column
FROM old_table o
JOIN new_table n ON n.id = o.id

From Sql Server 2008 onwards you can use Merge syntax
MERGE user target
USING user_new source
ON taget.ID = source.ID
WHEN MATCHED THEN
UPDATE
SET target.Column= source.Column1,target.column2=source.column2
WHEN NOT MATCHED BY TARGET THEN
INSERT (ID,Column1,Column2)
VALUES (source.ID,source.column1,source.column2);
or you can use the below query
INSERT INTO user(ID,column1,column2)
SELECT ID,column1,column2 FROM user_new AS source
WHERE NOT EXISTS (SELECT * FROM user WHERE ID = source.ID);
UPDATE target SET ...
FROM user AS target
INNER JOIN user_new AS source
ON target.ID = source.ID;

Sounds like you might need a Merge if you have sql server 2008+.

You can't do insert and update in a single query you have to do in seperate
select * from user where user_id not in (select user_new.user_id from user_new )
this query results the data for insert query similarly u have to update by replacing not in to in

Related

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

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

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;

PL/SQL Update Query

Attempting to update a table I have created with null values from another table I have created in PL/SQL:
I was able to utilize the below update in SQL Server but am running into issues within PL/SQL (dont ask why I am running it in both)
Overall_Inventory = Table created with some populated values and some null valuse; this is the table requiring updates to those null values
task_table = Table also created, but contains value needing to be updated into T1
update dbh.overall_inventory
set dbh.overall_inventory.case_due_date = tsk.TASK_ACTION_TIMESTAMP
from dbh.overall_inventory,
(SELECT tsk.INQ_KEY,
min(tsk.TASK_ACTION_TIMESTAMP) as TASK_ACTION_TIMESTAMP
FROM dbh.task_table tsk
inner join dbh.overall_inventory Inv
on tsk.INQ_KEY = inv.inq_key
where tsk.ACTION_CD = '324'
group by tsk.INQ_KEY
) tsk
where tsk.INQ_KEY = dbh.overall_inventory.inq_key`
Oracle doesn't support from clause in the update statement. In this situation merge statement can be used.
merge into overall_inventory oi
using (select tsk.inq_key,
min(tsk.task_action_timestamp) as task_action_timestamp
from task_table tsk
join overall_inventory Inv
on tsk.inq_key = inv.inq_key
where tsk.action_cd = '324'
group by tsk.inq_key) tsk
on (tsk.inq_key = oi.inq_key )
when matched then
update
set case_due_date = tsk.task_action_timestamp
where case_due_date is null -- as I understood only NULL values
-- need to be updated
Note: Not tested because no sample data and desired result were provided.
I think you're looking for update over a select:
UPDATE (
  SELECT product_id, category_id
  FROM product) st
SET st.category_id = 5
WHERE st.category_id = 4;

need clarification on where not exists clause

I am trying to insert only those records into #AltDealNames table for which DealName exists in #DistDeal table but not in #AltDealNames table. For this I am trying not exists clause. But it is not working as expected. Query is simply dumping records into #AltDealNames table.
insert into #AltDealNames
select d.DealName, d.ManagerScrubbed, d.BbgDealName, t.TrancheName, t.StreetCusip, t.ISIN, t.BbgTrancheName
from metric..Deal d join metric..Tranche t on d.DealName = t.DealName
where not exists(select 1 from #DistDeal dd join #AltDealNames ad on ad.DealName = dd.DealName)
Please help me to know if I am doing something wrong while building query.
If I understand correctly, you want an exists clause for #DistDeal and a not exists for #AltDealNames:
insert into #AltDealNames
select d.DealName, d.ManagerScrubbed, d.BbgDealName, t.TrancheName,
t.StreetCusip, t.ISIN, t.BbgTrancheName
from metric..Deal d join
metric..Tranche t
on d.DealName = t.DealName
where exists (select 1 from #DistDeal dd where dd.DealName = d.DealName) and
not exists (select 1 from #AltDealNames ad on ad.DealName = dd.DealName);
Note: when using insert, you should always include the list of column names.
Depending on how the optimizer sets up the actual physical query, the "where not exists" clause might run first, before anything is inserted by this query. Ie., it would only filter on values in #AltDealNames that were there from a previous query.
If you're trying to avoid inserting DealName values that are in #DistDeal, then maybe you want:
insert into #AltDealNames
select d.DealName, d.ManagerScrubbed, d.BbgDealName, t.TrancheName,
t.StreetCusip, t.ISIN, t.BbgTrancheName
from metric..Deal d
join metric..Tranche t on d.DealName = t.DealName
where not exists(select 1 from #DistDeal dd
where d.DealName = dd.DealName) -- Changed line

Problems inserting new data into SQL Server table

I am trying to do an if else insert into one table from another (a table type).
I am having problems where basically the first time the script runs it adds all data into the table OK but then if something is added to the source data afterwards, it does not add the new record and I don't know why.
I can't include the exact code but it looks like this...
UPDATE CUSTOMER
Set Target.Desc = Source.Desc
From #source source
WHERE Target.AccountNumber = Source.AccountNumber
IF ##ROWCOUNT=0
INSERT INTO CUSTOMER(AccountNumber, Desc)
SELECT Source.AccountNumber, Source.Desc
FROM #Source Source
I have also tried a traditional if else insert but it had the same results.
Can you see anything wrong that might be stopping the newly added records from being inserted?
Your current code will only work correctly if #source contains either all existing or all new rows.
You can use MERGE when this is not the case
MERGE CUSTOMER AS target
USING #source AS source
ON ( target.AccountNumber = source.AccountNumber )
WHEN MATCHED THEN
UPDATE SET [Desc] = source.[Desc]
WHEN NOT MATCHED THEN
INSERT (AccountNumber, [Desc])
VALUES (AccountNumber, [Desc]);
How about doing this instead of using ##ROWCOUNT
-- update existing customers
UPDATE c
SET c.Desc = Source.Desc
FROM #source source
INNER JOIN CUSTOMER c ON c.AccountNumber = Source.AccountNumber
-- insert new customers
INSERT INTO CUSTOMER(AccountNumber, Desc)
SELECT Source.AccountNumber, Source.Desc
FROM #Source Source
LEFT JOIN CUSTOMER c ON Source.AccountNumber = c.AccountNumber
WHERE c.AccountNumber IS NULL
-- update all existing rows
update c set
c.Desc = s.Desc
from CUSTOMER c
join #source s on s.AccountNumber=c.AccountNumber
-- insert all missing rows
insert into CUSTOMER (AccountNumber, Desc)
select s.AccountNumber, s.Desc
from #Source s
where not exists(
select *
from CUSTOMER c
where c.AccountNumber=s.AccountNumber
)
The first time, there is no data in your target so ##rowcount is 0.
Next time, the update updates all data and ##rowcount is not 0 and you get no data inserted.
You should not use ##rowcount but do what Andrew suggest: do both UPDATE and INSERT
or MERGE (do both in one statement)
##ROWCOUNT value contains the count of affected rows. the insert statement works only if all the records are new. and it does not go for updation. if any of the record got updated, it would not go for insertion even the source contains new records
If your requirement is to update existing records and Insert New records from source , you can use the below code.
-- update existing Rows
UPDATE CUSTOMER
SET CUSTOMER.Desc = SOURCE.Desc
from #SOURCE Source
WHERE Source.AccountNumber=CUSTOMER.AccountNumber
-- Insert New Data
INSERT INTO CUSTOMER (AccountNumber, Desc)
SELECT s.AccountNumber, s.Desc
FROM #Source Source
WHERE not exists( SELECT 1
FROM CUSTOMER
WHERE CUSTOMER.AccountNumber=Source.AccountNumber)