Подтвердить что ты не робот

Самый простой способ сравнить две схемы таблиц в SQL Server 2008?

Мне нужно делать проверки между базой данных разработки и выпуска и делать это вручную, что является медленным и не на 100% надежным (я только визуально просматриваю таблицы).

Есть ли быстрый и простой способ сравнить схемы таблиц автоматически? Может быть, даже функция, которая делает это прямо на SQL-сервере?

Изменить: я сравниваю только структуру, спасибо за указание на это.

4b9b3361

Ответ 1

Я поклонник SQL DBDiff, который является инструментом с открытым исходным кодом, который вы можете использовать для сравнения таблиц, представлений, функций, пользователей, и т.д. двух экземпляров баз данных SQL Server и сгенерировать изменение script между исходной и целевой базами данных.

Ответ 4

Я немного опоздал в игру... но этот script, который я сделал, хорошо сработал у меня. При необходимости он будет работать и через связанные серверы.

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

Ответ 5

Для бесплатного решения вы можете использовать Объекты управления SQL Server для вывода DDL script для каждой таблицы, представления, индекса, SP, UDF и т.д. Затем вы можете сравнить либо в коде, либо с помощью инструмента сравнения, такого как WinMerge.

Ответ 6

<ы > Су,

В Google это:

для структур:

см. также: С >

Ссылки по моим предыдущим ответам по какой-то причине больше не работают, поэтому другой ответ от 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)

Ответ 7

вы можете взглянуть на http://cdttools.com/2011/10/sql-diff-erence/ свою недорогую альтернативу, проведете схему между двумя базами данных и скажете, что изменилось. Затем вы можете использовать студию SQL Mgmt для создания "script → As Alter" для создания сценариев изменений. (предостережение: я написал это)

Ответ 8

Изменено немного BD. запрос, все кредиты идут ему. (Изменено SCHEMA_NAME(schema_id) на sys.schemas join, потому что SCHEMA_NAME(schema_id) работает с текущим контекстом db, который является master, изменяет сортировку и изменяет имена столбцов и добавляет столбец состояния)

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

Ответ 9

Вы можете использовать студийные инструменты SQL Management для создания сценариев из обеих баз данных. Затем используйте свой любимый инструмент сравнения текста, чтобы увидеть различия.

В старые времена это отлично поработало, но в SQL 2005 сгенерирован код script, и объекты больше не были созданы в том же порядке, поэтому сравнение текста менее полезно. Я не тестировал это в более поздних версиях SQL, поэтому он, возможно, был исправлен. Вы также можете попробовать http://exportsqlscript.codeplex.com/, который я с успехом использовал для вывода DDL в качестве скриптов для управления исходным кодом и сравнения версий.

Литература:

Ответ 10

Если две таблицы в одной базе данных, вы можете использовать этот запрос

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')