SQL: INSERT o UPDATE in automatico

Come far decidere direttamente allo script SQL se fare una INSERT o una UPDATE.

Quante volte vi sarà capitato di dover aggiornare una tabella con dei dati provenienti da una fonte esterna? Nella maggioranza dei casi, i dati da importare possono sia essere nuovi rispetto alla vostra tabella che essere degli aggiornamenti.
Scorrere con un cursore la tabella da importare e vedere record per record se è una novità o un aggiornamento è una scelta poco efficiente. Quale può essere allora una soluzione più performante?

Sfruttare la JOIN

La domanda necessaria da farsi è questa: in base a quale chiave riesco a capire se un record è una novità o un aggiornamento?

Una volta trovata la risposta, il meccanismo è semplice:

  • si metteranno in JOIN le due tabelle (da importare ed esistente) relazionandole proprio con la chiave individuata
  • la JOIN sarà una LEFT JOIN, con a sinistra la tabella da importare, e a destra quella già esistente
  • come noto, la LEFT JOIN restituirà una serie di colonne NULL nella tabella di destra nel caso non ci siano corrispondenze: sfruttando questa caratteristica potremo quindi individuare quali sono i record già esistenti e quali invece sono nuovi
  • ovviamente quelli nuovi saranno quelli con contenuto NULL, che sta a significare che i record della tabella di sinistra (da importare) NON sono già esistenti nella tabella di destra (esistente) e vanno quindi inseriti
  • quelli invece non-NULL sono già esistenti, e quindi andranno aggiornati
  • attenzione ad eseguire PRIMA la UPDATE e poi la INSERT; in caso contrario verranno aggiornati anche i record appena inseriti: i dati non vengono assolutamente danneggiati, ma sicuramente ci sarà una perdita di tempo

Esempio pratico

Un esempio aiuterà a comprendere più facilmente il meccanismo.

Immaginiamo di dover aggiornare una tabella di Dati Anagrafici con dei dati che ci vengono inviati periodicamente da un corrispondente; in questo caso, la chiave identificativa (univoca) sarà la Partita IVA.

Per comodità, avremo già importato i dati del nostro corrispondente in una tabella temporanea; i nomi delle colonne saranno gli stessi.

Impostiamo quindi la JOIN:

-- TS=TableSource, TT=TableTarget
SELECT
   TS.Descrizione, TS.PartitaIVA,
   TT.Descrizione, TT.PartitaIVA
FROM
   #tmpAnag TS LEFT JOIN ANAGRAFICHE TT ON TS.PartitaIVA=TT.PartitaIVA

Quando eseguiremo questa query, vederemo elencate delle corrispondenze esatte nel caso di record da aggiornare, mentre invece noteremo TT.Descrizione e TT.PartitaIVA a NULL nel caso di novità.

Sfrutteremo quindi la JOIN di riferimento per impostare prima una UPDATE…FROM…JOIN per fare gli aggiornamenti, poi una INSERT…SELECT…JOIN per fare gli inserimenti.

UPDATE

-- TS=TableSource, TT=TableTarget
UPDATE ANAGRAFICHE SET
   Denominazione=TS.Denominazione,
   Indirizzo=TS.Indirizzo,
   CAP=TS.CAP,
   Localita=TS.Localita,
   PartitaIVA=TS.PartitaIVA
FROM
   #tmpAnag TS LEFT JOIN ANAGRAFICHE TT ON TS.PartitaIVA=TT.PartitaIVA
-- fa correttamente la JOIN? Quindi c'è GIA'! ---> UPDATE

INSERT

-- TS=TableSource, TT=TableTarget
INSERT INTO ANAGRAFICHE
   (Denominazione,
    Indirizzo,
    CAP,
    Localita,
    PartitaIVA)
SELECT
   TS.Denominazione,
   TS.Indirizzo,
   TS.CAP,
   TS.Localita,
   TS.PartitaIVA
FROM
   #tmpAnag TS LEFT JOIN ANAGRAFICHE TT ON TS.PartitaIVA=TT.PartitaIVA
WHERE 
   TT.PartitaIVA IS NULL
-- non fa la JOIN? Quindi NON c'è! ---> INSERT

2 commenti:

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *