8 gennaio 2013

UPSERT in Oracle: MERGE statement

Consiglio l'uso dello statement MERGE nel caso in cui sia necessario eseguire un'operazione del tipo "insert or update", anche detta upsert.
Tipicamente si utilizza per aggiornare una tabella periodicamente, leggendo i dati da un'altra sorgente. In particolare, i dati nella sorgente sono completi, dove ci sono sia i record caricati nei precedenti aggiornamenti, che devono essere aggiornati, e sia quelli nuovi.
L’approccio più semplice e intuitivo sarebbe quello di svuotare la tabella di destinazione di aggiornamento e riempirla con tutti i dati della tabella sorgente.
Altro modo è demandare l'implementazione della logica al dbms e utilizzare l'operazione “MERGE”, che prende i valori della tabella inserendoli o aggiornandoli nell’altra in base al matching della condizione nella clausola “ON”.

Sintassi Oracle:
MERGE [ hint ]
   INTO [ schema. ] { table | view } [ t_alias ]
   USING { [ schema. ] { table | view }
         | subquery
         } [ t_alias ]
   ON ( condition )
   [ merge_update_clause ]
   [ merge_insert_clause ]
   [ error_logging_clause ] ;

Esempio:
MERGE INTO premiproduzione p               --< tabella di destinazione
USING (                                    --<
SELECT id_impiegato, stipendio, divisione  --< tabella o statement di selezione che indivia i record
FROM impiegati                             --<
sorgente
WHERE divisione = 18) i                    --<
ON (p.id_impiegato = i.id_impiegato)       --< chiave
WHEN MATCHED THEN                          --< c'è match, il record è già presente nella tabella di 

                                           --< destinazione
UPDATE SET p.premio = i.stipendio * 0.1    --< allora aggiorno i campi della tabella di destinazione
DELETE WHERE (i.stipendio < 49500)         --< cancello i record da premiproduzione se i.stipendio < 49500
WHEN NOT MATCHED THEN                      --< non c'è match, il record non è presente nella 

                                           --< tabella di destinazione
INSERT (id_impiegato, premio)              --< allora inserisco un nuovo record e popolo i campi 

                                           --< id_impiegato, premio
VALUES (i.id_impiegato, i.stipendio * 0.5) --< valorizzandoli con i campi della tabella sorgente
WHERE (i.stipendio > 49500);               --< inserisco solo i record che rispettano la condizione

                                           --< i.stipendio > 49500

Notare che:
A disposizione per chiarimenti

Nessun commento: