2013-08-09 16 views
5

Ho bisogno di unire i dati da una tabella del donatore in due tabelle di destinazione. La struttura è come sotto Se un projid non viene trovato nella tabella di traccia, ho bisogno di creare un nuovo componente nella tabella dei componenti e utilizzare il nuovo id da inserire nella tabella di traccia. Inoltre, per gli articoli che non esistono più nella tabella del donatore, la colonna 'attiva' della tabella di traccia deve essere contrassegnata come 0. Posso ottenere questo risultato in una singola dichiarazione di unione?Unisci i dati in due tabelle di destinazione

Donor Tabella

projid  | datestamp | Ownerid 
------------------------------------------------- 
c_abc  1-jan-2013  name1 
c_def  2-jan-2013  name3 
c_ghi  3-jan-2013  name4 

tabella di traccia

compid  |projid  |active | ... 
----------------------------------------------- 
123   c_abc  1 
124   c_xyz  1 
125   c_def  1 

tabella componente

compid  |ownerid 
------------------------- 
123  name1 
124  name2 
125  name3 

tabelle di output dopo l'unione:

tavolo componente

compid  |ownerid 
------------------------- 
123  name1 
124  name2 
125  name3 
126  name4 

tabella di traccia

compid  |projid  |active | ... 
----------------------------------------------- 
123   c_abc  1 
124   c_xyz  0 
125   c_def  1 
126   c_ghi  1 
+0

Da dove viene quel 'name4'? –

+0

nome4 proviene anche dalla tabella dei donatori – mhn

+0

@mhn - stai dicendo che c'è un'altra colonna nella tabella Donor che contiene quel testo? Se è così, puoi aggiungerlo al tuo esempio? –

risposta

5

In teoria, ci dovrebbe essere una soluzione per fare questo in un'unica istruzione, ma ho finora non è riuscito a trovarlo. *

Ecco come si può fare con due MERGE dichiarazioni:

WITH CTE_trgt AS 
(
    SELECT c.compid, c.ownerid, t.projid, t.active 
    FROM component c 
    INNER JOIN trace t ON c.compid = t.compid 
) 
MERGE CTE_trgt t 
USING Donor s 
ON t.projid = s.projid 
WHEN NOT MATCHED BY TARGET 
    THEN INSERT (ownerid) 
    VALUES (s.ownerid) 
OUTPUT 
    INSERTED.compid, s.projid, 1 INTO trace; 


MERGE trace t 
USING Donor s 
ON t.projid = s.projid 
WHEN NOT MATCHED BY SOURCE 
    THEN UPDATE SET t.active = 0; 

SQLFiddle DEMO


* parte con l'aggiornamento colonna Attivo:

WHEN NOT MATCHED BY SOURCE 
    THEN UPDATE SET t.active = 0 

dovrebbe essere in grado di inserirsi nella query superiore creando un single merge statement per tutte le operazioni, ma genera un errore:

View or function 't' is not updatable because the modification affects multiple base tables

anche se è ovviamente singola colonna, e regular non-merge update works fine. Forse qualcuno conosce una ragione e/o una soluzione per questo.

+0

Ciao Nenad, grazie mille per i tuoi input !! la prima dichiarazione di fusione è andata bene. Ma la dichiarazione che aggiorna il flag attivo nella tabella di trace non sono in grado di personalizzare il modo in cui voglio. Ho perso un'altra colonna donorid in traccia. Quindi ho bisogno di aggiornare solo quelle file in cui donorid = 'MyDonorId'. Non sono in grado di soddisfare questa clausola in cui punto sull'istruzione di fusione. Ho provato – mhn

+0

... MERGE (selezionare * da traccia dove donorid = 'MyDonorId') t UTILIZZO Donor s ON t.projid = s.projid QUANDO NON ABBINATO DA SOURCE THEN UPDATE SET t.active = 0; Si dice sintassi errata :( – mhn

+0

@mhn È possibile utilizzare la sintassi della tabella comune - 'WITH CTE', come nella prima istruzione per filtrare il target –