2010-10-18 9 views
20

Tengo que hacer comprobaciones entre una base de datos de desarrollo y lanzamiento y hacerlo manualmente, lo cual es lento y no es 100% confiable (solo inspecciono visualmente las tablas).¿La forma más fácil de diferir dos esquemas de tabla en SQL Server 2008?

¿Existe una manera rápida y fácil de comparar los esquemas de tablas automáticamente? Tal vez incluso una característica que hace esto integrado en el servidor SQL?

Editar: Estoy comparando estructura solamente, gracias por señalar esto.

+0

Nota: el PO está hablando acerca de la estructura, no datos. – RedFilter

+1

@RedFilter: se editó la pregunta para aclarar que, de hecho, era confuso –

+0

Por supuesto, sería útil si usted generó cambios y los puso en control de fuente para moverlos con el resto del código para esa versión del software. Entonces no tendrías que hacer todo esto diferente (y quizás mover accidentalmente algo que aún no está listo para pinchazos). – HLGEM

Respuesta

21

Soy un fan de SQL DBDiff, que es una herramienta de código abierto que puede utilizar para comparar las tablas, vistas, funciones, usuarios, etc., de dos instancias de bases de datos SQL Server y generar un script de cambio entre las bases de datos de origen y de destino.

+0

La herramienta diff es un poco insatisfactoria, tenía claras diferencias en las estructuras entre el origen y el destino y no las destacó en absoluto. Al decir eso, encontró algunos, simplemente no todos ... – Eric

6

¿Datos o estructura o ambos? Pruebe RedGate sql compare o compare datos. Ambos tienen pruebas gratuitas y son increíbles.

http://www.red-gate.com/products/SQL_Compare/index.htm

http://www.red-gate.com/products/SQL_Data_Compare/index.htm

+0

Solo la estructura. ¿Hay una versión gratuita de esa bestia de $ 400? – sooprise

+0

No hay una versión gratuita de nada que sea mejor que las herramientas de red_gate. Esto es algo en lo que deberías gastar el dinero. – HLGEM

+0

Acabo de descargar DB Diff y hace el trabajo para las tareas simples que hago. Sin embargo, tendré en cuenta a Red Gate en el futuro. – sooprise

2

Para una solución gratuita, puede usar SQL Server Managements Objects para generar el script DDL para cada tabla, vista, índice, SP, UDF, etc. Luego puede comparar, ya sea en código o usando una herramienta diff como WinMerge.

1

Soo,

buscado en Google este:

for structures:

see also:

enlaces Mis anteriores respuestas ya no funciona por alguna razón, así que aquí tiene otra respuesta de TechNet:

DECLARE @Sourcedb sysname 
DECLARE @Destdb sysname 
DECLARE @Tablename sysname 
DECLARE @SQL varchar(max) 

SELECT @Sourcedb = '<<SourceDatabaseName>>' 
SELECT @Destdb = '<<DestinationDatabaseName>>' 
SELECT @Tablename = '<<Tablename>>' -- '%' for all tables 

SELECT @SQL = ' SELECT Tablename = ISNULL(Source.tablename,Destination.tablename) 
         ,ColumnName = ISNULL(Source.Columnname,Destination.Columnname) 
         ,Source.Datatype 
         ,Source.Length 
         ,Source.precision 
         ,Destination.Datatype 
         ,Destination.Length 
         ,Destination.precision 
         ,[Column] = 
         Case 
         When Source.Columnname IS NULL then ''Column Missing in the Source'' 
         When Destination.Columnname IS NULL then ''Column Missing in the Destination'' 
         ELSE '''' 
         end 
         ,DataType = CASE WHEN Source.Columnname IS NOT NULL 
             AND Destination.Columnname IS NOT NULL 
             AND Source.Datatype <> Destination.Datatype THEN ''Data Type mismatch'' 
            END 
         ,Length = CASE WHEN Source.Columnname IS NOT NULL 
             AND Destination.Columnname IS NOT NULL 
             AND Source.Length <> Destination.Length THEN ''Length mismatch'' 
            END 
         ,Precision = CASE WHEN Source.Columnname IS NOT NULL 
             AND Destination.Columnname IS NOT NULL 
             AND Source.precision <> Destination.precision THEN ''precision mismatch'' 
            END 
         ,Collation = CASE WHEN Source.Columnname IS NOT NULL 
             AND Destination.Columnname IS NOT NULL 
             AND ISNULL(Source.collation_name,'''') <> ISNULL(Destination.collation_name,'''') THEN ''Collation mismatch'' 
             END 

    FROM 
( 
SELECT Tablename = so.name 
     , Columnname = sc.name 
     , DataType = St.name 
     , Length  = Sc.max_length 
     , precision = Sc.precision 
     , collation_name = Sc.collation_name 
    FROM ' + @Sourcedb + '.SYS.objects So 
    JOIN ' + @Sourcedb + '.SYS.columns Sc 
    ON So.object_id = Sc.object_id 
    JOIN ' + @Sourcedb + '.SYS.types St 
    ON Sc.system_type_id = St.system_type_id 
    AND Sc.user_type_id = St.user_type_id 
WHERE SO.TYPE =''U'' 
    AND SO.Name like ''' + @Tablename + ''' 
) Source 
FULL OUTER JOIN 
( 
    SELECT Tablename = so.name 
     , Columnname = sc.name 
     , DataType = St.name 
     , Length  = Sc.max_length 
     , precision = Sc.precision 
     , collation_name = Sc.collation_name 
    FROM ' + @Destdb + '.SYS.objects So 
    JOIN ' + @Destdb + '.SYS.columns Sc 
    ON So.object_id = Sc.object_id 
    JOIN ' + @Destdb + '.SYS.types St 
    ON Sc.system_type_id = St.system_type_id 
    AND Sc.user_type_id = St.user_type_id 
WHERE SO.TYPE =''U'' 
    AND SO.Name like ''' + @Tablename + ''' 
) Destination 
ON source.tablename = Destination.Tablename 
AND source.Columnname = Destination.Columnname ' 

EXEC (@Sql) 
0

Puede utilizar las herramientas de SQL Management Studio para 'generar secuencias de comandos' de ambas bases de datos. Luego, use su herramienta favorita de comparación de texto para ver las diferencias.

En los viejos tiempos, esto funcionaba muy bien, pero en SQL 2005 el código del script de generación cambió y los objetos ya no se crearon en el mismo orden, por lo que la comparación de texto es menos útil. No he probado esto en versiones más recientes de SQL por lo que puede haber sido corregido. También puede probar http://exportsqlscript.codeplex.com/ que he utilizado con buen éxito para generar DDL como scripts para el control de código fuente y para comparar versiones.

Referencias:

+0

Y, por supuesto, mi herramienta de comparación de texto favorita es Beyond Compare de http://www.scootersoftware.com/ –

+1

Intenté exactamente eso (generar los guiones, y yo incluso se usa más allá de comparar). Lamentablemente, como indica su publicación, fue un error debido al pedido ... – sooprise

+0

http://exportsqlscript.codeplex.com/ soluciona este problema. Y, como informé esto como un error para Microsoft y en el registro, alguien dijo "está arreglado en la próxima versión". Nunca vi la solución de Microsoft. –

1

que puede tomar un vistazo a http://cdttools.com/2011/10/sql-diff-erence/ es una alternativa de bajo costo, andarán esquema de entre dos bases de datos y le dirá cuál es cambiado A continuación, puede usar SQL Mgmt studio para generar "script-> As Alter" para generar scripts de cambio. (Advertencia: lo escribí)

0

Si dos tablas en misma base de datos, puede utilizar esta consulta

select c2.table_name,c2.COLUMN_NAME 
from [INFORMATION_SCHEMA].[COLUMNS] c2 
where table_name='table1' 
and c2.COLUMN_NAME not in (select column_name 
    from [INFORMATION_SCHEMA].[COLUMNS] 
    where table_name='table1') 
5

Estoy un poco tarde al juego ... pero este script que hice ha funcionado bien para mi. También funcionará en servidores vinculados si es necesario.

use master 
go 

DECLARE @Server1 VARCHAR(100) ='[CARNYSQLTEST1].'; --include a dot at the end 
DECLARE @DB1 VARCHAR(100) = '[ZipCrim]'; 
DECLARE @Table1 VARCHAR(100) = 'IntAction'; 

DECLARE @Server2 VARCHAR(100) ='[CARNYSQLDEV].'; --include a dot at the end 
DECLARE @DB2 VARCHAR(100) = '[ZipCrim]'; 
DECLARE @Table2 VARCHAR(100) = 'IntAction'; 

DECLARE @SQL NVARCHAR(MAX); 


SET @SQL = 
' 
SELECT Table1.ServerName, 
     Table1.DBName, 
     Table1.SchemaName, 
     Table1.TableName, 
     Table1.ColumnName, 
     Table1.name DataType, 
     Table1.Length, 
     Table1.Precision, 
     Table1.Scale, 
     Table1.Is_Identity, 
     Table1.Is_Nullable, 
     Table2.ServerName, 
     Table2.DBName, 
     Table2.SchemaName, 
     Table2.TableName, 
     Table2.ColumnName, 
     Table2.name DataType, 
     Table2.Length, 
     Table2.Precision, 
     Table2.Scale, 
     Table2.Is_Identity, 
     Table2.Is_Nullable 
FROM 
    (SELECT ''' + @Server1 + ''' ServerName, 
      ''' + @DB1 + ''' DbName, 
      SCHEMA_NAME(t.schema_id) SchemaName, 
      t.Name TableName, 
      c.Name ColumnName, 
      st.Name, 
      c.Max_Length Length, 
      c.Precision, 
      c.Scale, 
      c.Is_Identity, 
      c.Is_Nullable 
    FROM ' + @Server1 + @DB1 + '.sys.tables t 
      INNER JOIN ' + @Server1 + @DB1 + '.sys.columns c ON t.Object_ID = c.Object_ID 
      INNER JOIN sys.types st ON St.system_type_id = c.System_Type_id AND st.user_type_id = c.user_type_id 
    WHERE t.Name = ''' + @Table1 + ''') Table1 
    FULL OUTER JOIN 
    (SELECT ''' + @Server2 + ''' ServerName, 
      ''' + @DB2 + ''' DbName, 
      SCHEMA_NAME(t.schema_id) SchemaName, 
      t.name TableName, 
      c.name ColumnName, 
      st.Name, 
      c.max_length Length, 
      c.Precision, 
      c.Scale, 
      c.Is_Identity, 
      c.Is_Nullable 
    FROM ' + @Server2 + @DB2 + '.sys.tables t 
      INNER JOIN ' + @Server2 + @DB2 + '.sys.columns c ON t.Object_ID = c.Object_ID 
      INNER JOIN sys.types st ON St.system_type_id = c.System_Type_id AND st.user_type_id = c.user_type_id 
    WHERE t.Name = ''' + @Table2 + ''') Table2 
    ON Table1.ColumnName = Table2.ColumnName 
ORDER BY CASE WHEN Table1.ColumnName IS NULL THEN 2 ELSE 1 END, Table1.ColumnName 
' 

EXEC sp_executesql @SQL 
1

modificado un poco de BD.'s query, todo el crédito va a él. (Cambiado SCHEMA_NAME(schema_id) a sys.schemas se unen porque SCHEMA_NAME(schema_id) obras con db contexto actual, que es master, cambiaron la clasificación y cambiaron los nombres de columna y ha añadido la columna de estado)

USE master 
GO 

DECLARE 
    @Server1 VARCHAR(100) = 'Server1.', -- don't forget to include a dot at the end 
    @Server2 VARCHAR(100) = 'Server2.', -- don't forget to include a dot at the end 
    @DB1 VARCHAR(100) = 'Database1', 
    @DB2 VARCHAR(100) = 'Database2' 

DECLARE @SQL NVARCHAR(MAX); 

SET @SQL = ' 
SELECT 
    CASE 
     WHEN s1.[Column] IS NOT NULL 
      AND s2.[Column] IS NULL 
      THEN ''New'' 
     WHEN s1.[Column] IS NULL 
      AND s2.[Column] IS NOT NULL 
      THEN ''Deleted'' 
     WHEN s1.[Column] IS NOT NULL 
      AND s2.[Column] IS NOT NULL 
      AND (s1.[Type] <> s2.[Type] 
       OR s1.[Length] <> s2.[Length] 
       OR s1.[Precision] <> s2.[Precision] 
       OR s1.Scale <> s2.Scale 
       OR s1.IsNullable <> s2.IsNullable 
       OR s1.IsIdentity <> s2.IsIdentity 
       OR s1.IdentitySeed <> s2.IdentitySeed 
       OR s1.IdentityIncrement <> s2.IdentityIncrement 
       OR s1.DefaultValue <> s2.DefaultValue) 
      THEN ''Changed'' 
     ELSE ''Identical'' 
    END [Status], 
    s1.[Database], 
    s1.[Schema], 
    s1.[Table], 
    s1.[Column], 
    s1.[Type], 
    s1.IsCharType, 
    s1.[Length], 
    s1.[Precision], 
    s1.Scale, 
    s1.IsNullable, 
    s1.IsIdentity, 
    s1.IdentitySeed, 
    s1.IdentityIncrement, 
    s1.DefaultValue, 
    s1.[Order], 
    s2.[Database], 
    s2.[Schema], 
    s2.[Table], 
    s2.[Column], 
    s2.[Type], 
    s2.IsCharType, 
    s2.[Length], 
    s2.[Precision], 
    s2.Scale, 
    s2.IsNullable, 
    s2.IsIdentity, 
    s2.IdentitySeed, 
    s2.IdentityIncrement, 
    s2.DefaultValue, 
    s2.[Order] 
FROM (
    SELECT 
     ''' + @DB1 + ''' AS [Database], 
     s.name AS [Schema], 
     t.name AS [Table], 
     c.name AS [Column], 
     tp.name AS [Type], 
     CASE 
      WHEN tp.collation_name IS NOT NULL 
       THEN 1 
      ELSE 0 
     END AS IsCharType, 
     CASE 
      WHEN c.max_length = -1 
       THEN ''MAX'' 
      ELSE CAST(c.max_length AS VARCHAR(4)) 
     END AS [Length], 
     c.[precision], 
     c.scale, 
     c.is_nullable AS IsNullable, 
     c.is_identity AS IsIdentity, 
     CAST(ISNULL(ic.seed_value, 0) AS INT) AS IdentitySeed, 
     CAST(ISNULL(ic.increment_value, 0) AS INT) AS IdentityIncrement, 
     dc.definition AS DefaultValue, 
     c.column_id AS [Order] 
    FROM ' + @Server1 + @DB1 + '.sys.tables t 
     INNER JOIN ' + @Server1 + @DB1 + '.sys.schemas s ON s.schema_id = t.schema_id 
     INNER JOIN ' + @Server1 + @DB1 + '.sys.columns c ON c.object_id = t.object_id 
     INNER JOIN ' + @Server1 + @DB1 + '.sys.types tp ON tp.system_type_id = c.system_type_id 
     LEFT OUTER JOIN ' + @Server1 + @DB1 + '.sys.identity_columns ic ON ic.object_id = t.object_id AND ic.name = c.name 
     LEFT OUTER JOIN ' + @Server1 + @DB1 + '.sys.default_constraints dc ON dc.object_id = c.default_object_id 
    ) s1 
FULL OUTER JOIN (
    SELECT 
     ''' + @DB2 + ''' AS [Database], 
     s.name AS [Schema], 
     t.name AS [Table], 
     c.name AS [Column], 
     tp.name AS [Type], 
     CASE 
      WHEN tp.collation_name IS NOT NULL 
       THEN 1 
      ELSE 0 
     END AS IsCharType, 
     CASE 
      WHEN c.max_length = -1 
       THEN ''MAX'' 
      ELSE CAST(c.max_length AS VARCHAR(4)) 
     END AS [Length], 
     c.[precision], 
     c.scale, 
     c.is_nullable AS IsNullable, 
     c.is_identity AS IsIdentity, 
     CAST(ISNULL(ic.seed_value, 0) AS INT) AS IdentitySeed, 
     CAST(ISNULL(ic.increment_value, 0) AS INT) AS IdentityIncrement, 
     dc.definition AS DefaultValue, 
     c.column_id AS [Order] 
    FROM ' + @Server2 + @DB2 + '.sys.tables t 
     INNER JOIN ' + @Server2 + @DB2 + '.sys.schemas s ON s.schema_id = t.schema_id 
     INNER JOIN ' + @Server2 + @DB2 + '.sys.columns c ON c.object_id = t.object_id 
     INNER JOIN ' + @Server2 + @DB2 + '.sys.types tp ON tp.system_type_id = c.system_type_id 
     LEFT OUTER JOIN ' + @Server2 + @DB2 + '.sys.identity_columns ic ON ic.object_id = t.object_id AND ic.name = c.name 
     LEFT OUTER JOIN ' + @Server2 + @DB2 + '.sys.default_constraints dc ON dc.object_id = c.default_object_id 
    ) s2 
    ON s2.[Schema] = s1.[Schema] 
    AND s2.[Table] = s1.[Table] 
    AND s2.[Column] = s1.[Column] 
ORDER BY 
    CASE WHEN s1.[Database] IS NULL THEN s2.[Database] ELSE s1.[Database] END, 
    CASE WHEN s1.[Schema] IS NULL THEN s2.[Schema] ELSE s1.[Schema] END, 
    CASE WHEN s1.[Table] IS NULL THEN s2.[Table] ELSE s1.[Table] END, 
    CASE WHEN s1.[Order] IS NULL THEN s2.[Order] ELSE s1.[Order] END 
' 

EXEC sp_executesql @SQL 
Cuestiones relacionadas