2010-10-18 13 views
20

Devo fare controlli tra un database di sviluppo e di rilascio e farlo manualmente, che è sia lento che non affidabile al 100% (controllo solo visivamente le tabelle).Il modo più semplice per differenziare due schemi tabella in SQL Server 2008?

Esiste un modo semplice e veloce per confrontare automaticamente gli schemi di tabelle? Forse anche una funzionalità che fa questo direttamente nel server SQL?

Modifica: sto confrontando solo la struttura, grazie per averlo indicato.

+0

Nota: il PO sta parlando di struttura, non dati. – RedFilter

+1

@RedFilter: Modificato la domanda per chiarire che, ciò era davvero confuso –

+0

Ovviamente sarebbe di aiuto se tu avessi scriptato le modifiche e le avessi messo nel controllo del codice sorgente per essere spostato con il resto del codice per quella versione del software. Quindi non dovresti fare tutto questo diff (e forse spostando accidentalmente qualcosa non ancora pronto per prod.) – HLGEM

risposta

21

sono un fan di SQL DBDiff, che è uno strumento open source è possibile utilizzare per confrontare le tabelle, viste, funzioni, utenti, ecc di due istanze di database SQL Server e generare uno script di modifica tra i database di origine e di destinazione.

+0

Lo strumento diff è un po 'scadente, ho avuto chiare differenze nelle strutture tra sorgente e destinazione e non le evidenziavo affatto. Dicendo questo, ha trovato alcuni, solo non tutti .. – Eric

6

Dati o struttura o entrambi? Prova il confronto di dati o confronto di dati di RedGate. Entrambi hanno prove libere e sono fantastici.

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

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

+0

Proprio la struttura. Esiste una versione gratuita di quella bestia da $ 400? – sooprise

+0

Non c'è una versione gratuita di qualcosa che sia migliore degli strumenti di red_gate. Questo è qualcosa su cui dovresti spendere i soldi. – HLGEM

+0

Ho appena scaricato DB Diff e il lavoro viene svolto per le semplici attività che svolgo. Terrò comunque in mente Red Gate in futuro. – sooprise

2

Per una soluzione gratuita, è possibile utilizzare SQL Server Managements Objects per generare lo script DDL per ogni tabella, vista, indice, SP, UDF, ecc. Quindi è possibile confrontare, in codice o utilizzando uno strumento di diff come WinMerge.

1

Soo,

Googled questo:

for structures:

see also:

links I miei precedenti risposte non funziona più, per qualche motivo, quindi ecco un'altra risposta da 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

È possibile utilizzare gli strumenti SQL Management Studio per 'Genera script' da entrambi i database. Quindi usa il tuo strumento di comparazione di testo preferito per vedere eventuali differenze.

In passato, questo funzionava benissimo, ma in SQL 2005 il codice di script generato era cambiato e gli oggetti non venivano più creati nello stesso ordine, quindi il confronto del testo è meno utile. Non ho provato questo in versioni più recenti di SQL, quindi potrebbe essere stato risolto. Puoi anche provare http://exportsqlscript.codeplex.com/ che ho usato con successo per generare DDL come script per il controllo del codice sorgente e per confrontare le versioni.

Riferimenti:

+0

E, naturalmente, il mio strumento di comparazione di testo preferito è Beyond Compare da http://www.scootersoftware.com/ –

+1

Ho provato quella cosa esatta (generando gli script, e io anche usato senza paragoni). Sfortunatamente, come afferma il tuo post, è stato un errore dovuto all'ordinazione ... – sooprise

+0

http://exportsqlscript.codeplex.com/ risolve questo problema. E, come ho segnalato questo come un bug a Microsoft e nel registro qualcuno ha detto "è stato risolto nella prossima versione". Non ho mai visto la correzione da Microsoft. –

1

si può dare un'occhiata a http://cdttools.com/2011/10/sql-diff-erence/ sua un'alternativa a basso costo, cammineranno schema tra due database e ti dirà che cosa è cambiato. È quindi possibile utilizzare SQL Mgmt Studio per generare "script-> As Alter" per creare script di modifica. (Avvertimento: ho scritto)

0

Se due tabelle nello stesso database, è possibile utilizzare questa query

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

Sono un po 'in ritardo al gioco ... ma questo script ho fatto ha funzionato bene per me. Funzionerà anche su server collegati, se necessario.

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

modificato un po 'di BD.'s query, tutto il merito va a lui. (Cambiato SCHEMA_NAME(schema_id) a sys.schemas unirsi perché SCHEMA_NAME(schema_id) opere con db contesto attuale, che è master, cambiato l'ordinamento e cambiati i nomi delle colonne e ha aggiunto la colonna Stato)

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 
Problemi correlati