Blog   ❯   Autore: Fabio MoschiniData: 13.10.2022

Confronto tra strutture di database

alt text for image

Come confrontare le strutture di due database

Nel precedente articolo, abbiamo visto come utilizzare INFORMATION_SCHEMA per avere informazioni sui metadati di un database.
Ora vedremo come sfruttare questo strumento per confrontare le strutture di due database con l'obiettivo di evidenziare le differenze tra di essi.

JOIN: breve ripasso

Attraverso l'utilizzo delle JOIN, è possibile leggere dati correlati tra due o più tabelle.
Le condizioni di JOIN indicano al motore SQL come leggere le righe da una tabella in funzione dei dati presenti sulle righe di un'altra tabella e sono espresse tramite i comandi SQL:

  • - INNER JOIN: seleziona e mette in relazione le righe di due tabelle per le quali c'è una corrispondenza dei valori nelle colonne indicate per la correlazione:
    alt text for image


  • - LEFT OUTER JOIN (LEFT JOIN): seleziona tutte le righe della prima tabella (quella di sinistra) con le righe della seconda tabella (quella di destra) che soddisfano la condizione di join. Le righe della prima tabella senza corrispondenza nella seconda sono estese con valori nulli:
    alt text for image


  • - RIGHT OUTER JOIN (RIGHT JOIN): lavora in modo simmetrico rispetto alla LEFT OUTER JOIN, ovvero seleziona tutte le righe della seconda tabella (quella di destra) con le righe della prima tabella (quella di sinistra) che soddisfano la condizione di join. Le righe della seconda tabella senza corrispondenza nella prima sono estese con valori nulli:
    alt text for image


  • - FULL OUTER JOIN (FULL JOIN): seleziona tutte le righe della prima e della seconda tabella, ottenute con LEFT OUTER JOIN e RIGHT OUTER JOIN:
    alt text for image


Quale JOIN utilizzare per il nostro obiettivo?

Attraverso l'operazione di FULL OUTER JOIN (equivalente a FULL JOIN) possiamo determinare le tabelle definite soltanto in uno dei due database.
Per fare questo, è sufficiente applicare questo tipo di JOIN alle tabelle DB_Source.INFORMATION_SCHEMA.TABLES e DB_Target.INFORMATION_SCHEMA.TABLES, dove DB_Source e DB_Target sono i due database da analizzare:
-- Search for different tables SELECT ISNULL(SRC.TABLE_TYPE, TGT.TABLE_TYPE) AS [TYPE], ISNULL(SRC.TABLE_SCHEMA, TGT.TABLE_SCHEMA) AS [SCHEMA], ISNULL(SRC.TABLE_NAME, TGT.TABLE_NAME) AS [NAME], 'Defined in ' + CASE WHEN SRC.TABLE_CATALOG IS NULL THEN 'Target' ELSE 'Source' END + ' but missing in ' + CASE WHEN SRC.TABLE_CATALOG IS NULL THEN 'Source' ELSE 'Target' END AS [NOTE] FROM DB_Source.INFORMATION_SCHEMA.TABLES AS SRC FULL OUTER JOIN DB_Target.INFORMATION_SCHEMA.TABLES AS TGT ON SRC.TABLE_SCHEMA = TGT.TABLE_SCHEMA AND SRC.TABLE_NAME = TGT.TABLE_NAME AND SRC.TABLE_TYPE = TGT.TABLE_TYPE WHERE SRC.TABLE_CATALOG IS NULL OR TGT.TABLE_CATALOG IS NULL

Il risultato della query è:
alt text for image

In modo analogo, possiamo determinare le differenze anche a livello di colonne:
-- Search for different columns on same tables SELECT SRC.TABLE_CATALOG, SRC.TABLE_SCHEMA, SRC.TABLE_NAME, SRC.COLUMN_NAME, TGT.TABLE_CATALOG, TGT.TABLE_SCHEMA, TGT.TABLE_NAME, TGT.COLUMN_NAME, '||',* FROM DB_Source.INFORMATION_SCHEMA.COLUMNS AS SRC FULL OUTER JOIN DB_Target.INFORMATION_SCHEMA.COLUMNS AS TGT ON SRC.TABLE_SCHEMA = TGT.TABLE_SCHEMA AND SRC.TABLE_NAME = TGT.TABLE_NAME AND SRC.COLUMN_NAME = TGT.COLUMN_NAME WHERE ISNULL(SRC.TABLE_SCHEMA, '') <> ISNULL(TGT.TABLE_SCHEMA, '') OR ISNULL(SRC.TABLE_NAME, '') <> ISNULL(TGT.TABLE_NAME, '') OR ISNULL(SRC.COLUMN_NAME, '') <> ISNULL(TGT.COLUMN_NAME, '')

Questo script evidenzia le colonne definite soltanto in uno dei due database. Sono elencate anche tutte le colonne appartenenti a tabelle presenti soltanto in un database. Il risultato della query è:
alt text for image


Con la stessa tecnica, è possibile determinare le differenze anche per quanto riguarda le altre tipologie di entità definite su un database, come vincoli d'integrità, indici, chiavi primarie, stored procedure o function, trigger.