Programming Notes
Think it, Code it, Run it    moschini.cloud  

Confronto tra strutture di database
Data pubblicazione: 13 ottobre 2022

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: Join
  • 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: Join
  • 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: Join
  • FULL OUTER JOIN (FULL JOIN): seleziona tutte le righe della prima e della seconda tabella, ottenute con LEFT OUTER JOIN e RIGHT OUTER JOIN: Join

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 [SCHEMA],
       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 è:


Result

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 è:


Result

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.