Comparar la estructura de dos bases de datos

Una aplicación funciona en desarrollo, pero falla al desplegarse porque una columna tiene otra longitud, permite valores nulos o utiliza un tipo diferente en producción. Revisar las tablas una por una hace fácil pasar por alto una diferencia pequeña.

Qué necesitamos distinguir

El esquema es la definición estructural de los objetos de una base. En tipos numéricos, la precisión es la cantidad total de dígitos y la escala, los dígitos decimales; la nulabilidad indica si una columna admite NULL.

Compararemos columnas por esquema, tabla y nombre. El resultado separará columnas ausentes de definiciones diferentes y mostrará tipo, longitud, precisión, escala y nulabilidad.

Consulta

/*
    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

Parámetros o permisos

Sustituye BaseDesarrollo y BaseProduccion por bases de la misma instancia. Ejecuta la consulta desde una base cuya intercalación pueda utilizarse para comparar los nombres; COLLATE DATABASE_DEFAULT evita un conflicto común cuando las bases usan intercalaciones distintas. Se necesita visibilidad de metadatos en ambas bases. max_length se expresa en bytes: en nvarchar y nchar, salvo max, normalmente corresponde al doble del número de caracteres.

Cómo leer el resultado

EXCEPT compara proyecciones completas y devuelve las filas presentes en el primer conjunto pero no en el segundo.

Una columna presente en una sola base aparece como “Solo en origen” o “Solo en destino”. Si existe en ambas, se muestra únicamente cuando al menos una propiedad comparada cambia. EXCEPT permite comparar también valores nulos sin construir una condición separada por propiedad. Las columnas de ambos SELECT conservan el mismo orden y tipos compatibles. La consulta compara estructura de columnas, no datos. Tampoco intenta generar instrucciones ALTER; primero necesitamos decidir cuál definición es la esperada y qué impacto tendría modificarla.

Qué conclusión sí permite obtener

Permite localizar columnas faltantes y diferencias en las propiedades estructurales incluidas entre dos bases accesibles de la misma instancia.

Qué conclusión todavía no permite obtener

No compara IDENTITY, columnas calculadas, índices, llaves, restricciones, valores predeterminados, triggers, permisos ni código SQL. Los tipos definidos por el usuario también requieren revisar su esquema y definición, no solo el nombre mostrado.

Siguiente comprobación razonable

Clasifica cada diferencia como esperada o pendiente de despliegue. Después revisa dependencias, datos existentes y scripts de migración antes de proponer un cambio de estructura.

Índice del recorrido

Desarrollo y exploración

22 artículos de Desarrollo y exploración
  1. 01Buscar una tabla o vista por nombre
  2. 02Buscar una columna en toda la base
  3. 03Buscar texto dentro de procedimientos, vistas y funciones
  4. 04Consultar dependencias de un objeto
  5. 05Listar relaciones y llaves foráneas
  6. 06Consultar llaves primarias, restricciones únicas e índices
  7. 07Listar columnas con tipo, longitud, nulabilidad y valor predeterminado
  8. 08Encontrar triggers y sus tablas asociadas
  9. 09Encontrar objetos modificados recientemente
  10. 10Obtener conteos aproximados de todas las tablas
  11. 11Medir el espacio utilizado por cada tabla
  12. 12Revisar columnas IDENTITY y su valor actual
  13. 13Detectar registros duplicados por una clave de negocio
  14. 14Detectar registros huérfanos
  15. 15Comparar dos conjuntos de datos
  16. 16Validar conversiones antes de modificar una columna
  17. 17Ejecutar un UPDATE con validación y reversión controlada
  18. 18Ejecutar un DELETE con respaldo lógico y reversión controlada
  19. 19Comparar la estructura de dos bases de datos
  20. 20Describir el resultado de una consulta o procedimiento
  21. 21Encontrar tablas sin llave primaria
  22. 22Buscar un valor en columnas seleccionadas