2011-09-07 10 views
18

Attualmente sto usando il seguente codice di unione per migrare la data dall'origine alla destinazione. Ho un nuovo requisito per estendere il codice sottostante per eliminare il record dal sorgente una volta che un aggiornamento/inserto viene eseguito sulla destinazione. Questo è possibile utilizzando merge (tutti gli esempi che vedo in rete avevano eseguendo del/inserimento/aggiornamento nel bersaglio non sulla fonte)Come eliminare dall'origine utilizzando il comando MERGE in SQL Server 2008?

MERGE Target1 AS T 
USING Source1 AS S 
ON (T.EmployeeID = S.EmployeeID) 
WHEN NOT MATCHED BY TARGET AND S.EmployeeName LIKE 'S%' 
    THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName) 
WHEN MATCHED 
    THEN UPDATE SET T.EmployeeName = S.EmployeeName 
WHEN NOT MATCHED BY SOURCE AND T.EmployeeName LIKE 'S%' 
    THEN DELETE ; 
+1

Non si può fare come parte di una singola istruzione. Ogni istruzione di modifica dei dati apporta solo modifiche a una singola tabella. –

+0

Grazie Damien. – nfa379

risposta

28

È possibile utilizzare la clausola di uscita per catturare i modificati righe/inseriti a una variabile di tabella e utilizzarla con un'istruzione delete dopo l'unione.

DECLARE @T TABLE(EmployeeID INT); 

MERGE Target1 AS T 
USING Source1 AS S 
ON (T.EmployeeID = S.EmployeeID) 
WHEN NOT MATCHED BY TARGET AND S.EmployeeName LIKE 'S%' 
    THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName) 
WHEN MATCHED 
    THEN UPDATE SET T.EmployeeName = S.EmployeeName 
WHEN NOT MATCHED BY SOURCE AND T.EmployeeName LIKE 'S%' 
    THEN DELETE 
OUTPUT S.EmployeeID INTO @T; 

DELETE Source1 
WHERE EmployeeID in (SELECT EmployeeID 
        FROM @T); 
2


Nizza Reponse, ma il codice sarà eliminare la riga dalla tabella di destinazione, ecco un exemple nel quale è possibile eliminare le righe dalla destinazione di origine, senza danneggiare la vostra tabella di destinazione:

if OBJECT_ID('audit.tmp1') IS NOT NULL 
    DROP TABLE audit.tmp1 

select * 
into audit.tmp1 
from 
(
select 1 id, 'aa' nom, convert(date,'2014-01-01') as dd UNION ALL 
select 2 id, 'bb' nom, convert(date,'2013-07-12') as dd UNION ALL 
select 3 id, 'cc' nom, convert(date,'2012-08-21') as dd UNION ALL 
select 4 id, 'dd' nom, convert(date,'2011-11-15') as dd UNION ALL 
select 5 id, 'ee' nom, convert(date,'2010-05-16') as dd) T 


if OBJECT_ID('audit.tmp2') IS NOT NULL 
DROP TABLE audit.tmp2 

select * 
into audit.tmp2 
from 
(
select 1 id, 'aAa' nom, convert(date,'2014-01-14') as dd UNION ALL 
select 2 id, 'bbB' nom, convert(date,'2013-06-13') as dd UNION ALL 
select 4 id, 'dDD' nom, convert(date,'2012-11-05') as dd UNION ALL 
select 6 id, 'FFf' nom, convert(date,'2014-01-12') as dd) T 


SELECT * FROM audit.tmp1 order by 1 
SELECT * FROM audit.tmp2 order by 1 


DECLARE @T TABLE(ID INT); 

MERGE audit.tmp2 WITH (HOLDLOCK) AS T 
USING (SELECT * FROM audit.tmp1 WHERE nom <> 'dd') AS S 
ON (T.id = S.id) 
WHEN NOT MATCHED BY TARGET 
THEN INSERT(id, nom, dd) VALUES(S.id, S.nom, S.dd) 
WHEN MATCHED 
THEN UPDATE SET T.nom = S.nom, T.dd = S.dd 
WHEN NOT MATCHED BY SOURCE 
THEN UPDATE SET T.id = T.id OUTPUT S.id INTO @T; 

DELETE tmp1 
FROM audit.tmp1 
INNER JOIN 
@T AS DEL 
    ON DEL.id = tmp1 .id 


SELECT * FROM audit.tmp1 ORDER BY 1 
SELECT * FROM audit.tmp2 ORDER BY 1 

Spero che questo ti possa aiutare.

0

è anche possibile utilizzare il codice qui sotto

drop table energydata 

create table temp_energydata 
(
webmeterID int, 
DT DateTime , 
kWh varchar(10) 
) 

Insert into temp_energydata 
select 1,getdate()-10, 120 
union 
select 2,getdate()-9, 140 
union 
select 3,getdate()-6, 37 
union 
select 4,getdate()-3, 40 
union 
select 5,getdate()-1, 240 

create table energydata 
(
webmeterID int, 
DT DateTime , 
kWh varchar(10) 
) 

Insert into energydata (webmeterID,kWh) 
select 1, 120 
union 
select 2, 140 
union 
select 3, 37 
union 
select 4, 40 

select * from energydata 
select * from temp_energydata 

begin tran ABC 

DECLARE @T TABLE(ID INT); 

MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target 
USING dbo.temp_energydata AS source 
    ON target.webmeterID = source.webmeterID 
    AND target.kWh = source.kWh 

WHEN MATCHED THEN 
    UPDATE SET target.DT = source.DT 

WHEN NOT MATCHED BY source THEN delete 
OUTPUT source.webmeterID INTO @T; 


DELETE temp_energydata 
WHERE webmeterID in (SELECT webmeterID 
        FROM @T); 
    --INSERT (webmeterID, DT, kWh) 
    --VALUES (source.webmeterID, source.DT, source.kWh) 


rollback tran ABC 
commit tran ABC