Compare the structure of two databases

An application works in development, but fails to deploy because a column has a different length, allows null values, or uses a different type in production. Going through the tables one by one makes it easy to miss a small difference.

What we need to distinguish

The schema is the structural definition of database objects. For numeric types, precision is the total number of digits and scale is the decimal digits; nullability indicates whether a column accepts NULL.

We will compare columns by schema, table and name. The result will separate missing columns of different definitions and display type, length, precision, scale, and nullability.

Query

/*
    Antes de ejecutar:
        Revisa la base activa, los nombres de objetos, los parámetros y los permisos.
        Adapta el ejemplo a tu modelo y pruébalo primero en un ambiente controlado.
*/

SET NOCOUNT ON;
GO
-- Consulta
WITH ColumnasOrigen AS
(
    SELECT
        s.name COLLATE DATABASE_DEFAULT AS Esquema,
        t.name COLLATE DATABASE_DEFAULT AS Tabla,
        c.name COLLATE DATABASE_DEFAULT AS Columna,
        ty.name COLLATE DATABASE_DEFAULT AS Tipo,
        c.max_length AS LongitudBytes,
        c.precision AS Precision,
        c.scale AS Escala,
        c.is_nullable AS PermiteNulos
    FROM BaseDesarrollo.sys.tables AS t
    INNER JOIN BaseDesarrollo.sys.schemas AS s
        ON s.schema_id = t.schema_id
    INNER JOIN BaseDesarrollo.sys.columns AS c
        ON c.object_id = t.object_id
    INNER JOIN BaseDesarrollo.sys.types AS ty
        ON ty.user_type_id = c.user_type_id
),
ColumnasDestino AS
(
    SELECT
        s.name COLLATE DATABASE_DEFAULT AS Esquema,
        t.name COLLATE DATABASE_DEFAULT AS Tabla,
        c.name COLLATE DATABASE_DEFAULT AS Columna,
        ty.name COLLATE DATABASE_DEFAULT AS Tipo,
        c.max_length AS LongitudBytes,
        c.precision AS Precision,
        c.scale AS Escala,
        c.is_nullable AS PermiteNulos
    FROM BaseProduccion.sys.tables AS t
    INNER JOIN BaseProduccion.sys.schemas AS s
        ON s.schema_id = t.schema_id
    INNER JOIN BaseProduccion.sys.columns AS c
        ON c.object_id = t.object_id
    INNER JOIN BaseProduccion.sys.types AS ty
        ON ty.user_type_id = c.user_type_id
)
SELECT
    COALESCE(o.Esquema, d.Esquema) AS Esquema,
    COALESCE(o.Tabla, d.Tabla) AS Tabla,
    COALESCE(o.Columna, d.Columna) AS Columna,
    CASE
        WHEN o.Columna IS NULL THEN N'Solo en destino'
        WHEN d.Columna IS NULL THEN N'Solo en origen'
        ELSE N'Definición diferente'
    END AS Diferencia,
    o.Tipo AS TipoOrigen,
    d.Tipo AS TipoDestino,
    o.LongitudBytes AS LongitudOrigen,
    d.LongitudBytes AS LongitudDestino,
    o.Precision AS PrecisionOrigen,
    d.Precision AS PrecisionDestino,
    o.Escala AS EscalaOrigen,
    d.Escala AS EscalaDestino,
    o.PermiteNulos AS NulosOrigen,
    d.PermiteNulos AS NulosDestino
FROM ColumnasOrigen AS o
FULL OUTER JOIN ColumnasDestino AS d
    ON d.Esquema = o.Esquema
   AND d.Tabla = o.Tabla
   AND d.Columna = o.Columna
WHERE o.Columna IS NULL
   OR d.Columna IS NULL
   OR EXISTS
      (
          SELECT
              o.Tipo, o.LongitudBytes, o.Precision,
              o.Escala, o.PermiteNulos
          EXCEPT
          SELECT
              d.Tipo, d.LongitudBytes, d.Precision,
              d.Escala, d.PermiteNulos
      )
ORDER BY
    Esquema,
    Tabla,
    Columna;
GO

Parameters or permissions

Replace BaseDevelopment and BaseProduction with bases of the same instance. Runs the query from a base whose collation can be used to compare names; COLLATE DATABASE_DEFAULT avoids a common conflict when bases use different collations. Metadata visibility is needed in both databases. max_length is expressed in bytes: in nvarchar and nchar, except max, it usually corresponds to twice the number of characters.

How to read the result

EXCEPT compares complete projections and returns rows present in the first set but not the second.

A column present in a single database appears as “Source only” or “Destination only”. If it exists in both, it is displayed only when at least one compared property changes. EXCEPT allows you to also compare null values ​​without constructing a separate condition per property. The columns of both SELECTs retain the same order and compatible types. The query compares column structure, not data. It also does not attempt to generate ALTER statements; We first need to decide which definition is the expected one and what impact modifying it would have.

What this does establish

Allows you to locate missing columns and differences in included structural properties between two accessible databases of the same instance.

What this still does not establish

It does not compare IDENTITY, calculated columns, indexes, keys, constraints, default values, triggers, permissions or SQL code. User-defined types also require reviewing their schema and definition, not just the display name.

Next reasonable check

Classify each difference as expected or pending deployment. Then review dependencies, existing data, and migration scripts before proposing a structure change.

Path index

Development and exploration

22 articles in Development and exploration
  1. 01Search for a table or view by name
  2. 02Search for a column across the database
  3. 03Search for text inside procedures, views, and functions
  4. 04Inspect the dependencies of an object
  5. 05List relationships and foreign keys
  6. 06Inspect primary keys, unique constraints, and indexes
  7. 07List columns with type, length, nullability, and default value
  8. 08Find triggers and their associated tables
  9. 09Find recently modified objects
  10. 10Get approximate row counts for every table
  11. 11Measure the space used by each table
  12. 12Inspect IDENTITY columns and their current value
  13. 13Find duplicate rows by business key
  14. 14Find orphaned rows
  15. 15Compare two data sets
  16. 16Validate conversions before changing a column
  17. 17Run an UPDATE with controlled validation and rollback
  18. 18Run a DELETE with a logical backup and controlled rollback
  19. 19Compare the structure of two databases
  20. 20Describe the result of a query or stored procedure
  21. 21Find tables without a primary key
  22. 22Search selected columns for a value