2010-10-18 67 views
20

我必须在开发和发布数据库之间进行检查,并手动执行此操作,这既缓慢又不是100%可靠(我只是通过目测检查表)。最简单的方法来比较SQL Server 2008中的两个表模式?

是否有一种快速简单的方法来自动比较表格模式?也许即使是内置于SQL Server中的功能呢?

编辑:我只比较结构,谢谢你指出这一点。

+0

注:OP谈论结构,而不是数据。 – RedFilter 2010-10-18 18:56:01

+1

@RedFilter:编辑了这个问题来澄清,这确实令人困惑 – 2010-10-18 18:57:47

+0

当然,如果您编写脚本更改并将它们放在源代码管理中以便与该版本的软件的其余代码一起移动,它将会有所帮助。那么你不需要做所有这些差异(也可能意外地将一些尚未准备好的东西移动) – HLGEM 2010-10-18 19:13:34

回答

21

我的SQL DBDiff风扇,这是一个开源工具,您可以使用比较表,视图,功能,用户等SQL Server数据库的两个实例并在源数据库和目标数据库之间生成更改脚本。

+0

差异工具有点欠佳,我在源和目标之间的结构上有明显的差异,它根本没有突出显示它们。在说,它发现了一些,但不是全部.. – Eric 2015-11-18 01:11:24

6

数据或结构或两者兼而有之?尝试RedGate SQL比较或数据比较。他们都有免费试用,很棒。

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

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

+0

只是结构。有没有400美元的野兽的免费版本? – sooprise 2010-10-18 18:53:34

+0

没有任何比red_gate的工具更好的免费版本。这是你应该花钱的东西。 – HLGEM 2010-10-18 19:11:33

+0

我刚刚下载了DB Diff,它为我做的简单任务完成了工作。尽管如此,我会在未来记住红门。 – sooprise 2010-10-18 19:16:20

1

洙,

Google搜索这样的:

for structures

see also

我以前的答案链接不会出于某种原因不再起作用,所以这里是从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

可以使用SQL Management Studio中的工具‘生成脚本’从这两个数据库。然后使用您最喜爱的文本比较工具来查看任何差异。

在过去,这很好用,但在SQL 2005中,生成的脚本代码发生了变化,对象不再以相同的顺序创建,所以文本比较没那么有用。我还没有在更新版本的SQL中测试过它,所以它可能已经修复。您也可以尝试使用http://exportsqlscript.codeplex.com/,我已经很成功地将DDL用作源代码控制和比较版本的脚本。

参考文献:

+0

当然,我最喜欢的文本比较工具是来自http://www.scootersoftware.com/ – 2010-10-18 19:08:52

+1

Beyond Compare我尝试了确切的事情(生成脚本,我甚至用于比较)。不幸的是,正如您的文章所述,由于订购而失败...... – sooprise 2010-10-18 21:05:52

+0

http://exportsqlscript.codeplex.com/确实解决了这个问题。而且,正如我向微软报告这个错误并在日志中所说的那样“它在下一个版本中已修复”。我从来没有见过微软的修复。 – 2010-10-20 13:44:27

1

你可以在http://cdttools.com/2011/10/sql-diff-erence/它的低成本替代看一看,会走两个数据库之间的模式,告诉你什么改变。然后,您可以使用SQL Mgmt studio生成“script-> As Alter”来构建更改脚本。 (警告:我写的)

0

如果在同一个数据库中的两个表,你可以使用这个查询

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

我有点太迟了......但这个剧本我做了运作良好为了我。如果需要,它也可以跨链接服务器工作。

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

修改了一下的BD.'s query,都归功于他。 (改变SCHEMA_NAME(schema_id)到sys.schemas加入,因为SCHEMA_NAME(schema_id)作品与是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