我必须在开发和发布数据库之间进行检查,并手动执行此操作,这既缓慢又不是100%可靠(我只是通过目测检查表)。最简单的方法来比较SQL Server 2008中的两个表模式?
是否有一种快速简单的方法来自动比较表格模式?也许即使是内置于SQL Server中的功能呢?
编辑:我只比较结构,谢谢你指出这一点。
我必须在开发和发布数据库之间进行检查,并手动执行此操作,这既缓慢又不是100%可靠(我只是通过目测检查表)。最简单的方法来比较SQL Server 2008中的两个表模式?
是否有一种快速简单的方法来自动比较表格模式?也许即使是内置于SQL Server中的功能呢?
编辑:我只比较结构,谢谢你指出这一点。
我的SQL DBDiff风扇,这是一个开源工具,您可以使用比较表,视图,功能,用户等SQL Server数据库的两个实例并在源数据库和目标数据库之间生成更改脚本。
差异工具有点欠佳,我在源和目标之间的结构上有明显的差异,它根本没有突出显示它们。在说,它发现了一些,但不是全部.. – Eric 2015-11-18 01:11:24
数据或结构或两者兼而有之?尝试RedGate SQL比较或数据比较。他们都有免费试用,很棒。
对于免费的解决方案,您可以使用SQL Server Managements Objects为每个表,视图,索引,SP,UDF等输出DDL脚本。然后,您可以使用代码或使用diff工具(如WinMerge)进行比较。
有一些商业产品可以做到这一点; Visual Studio 2010 Premium Edition可以比较模式。
有些人:
http://www.red-gate.com/products/SQL_Compare/index.htm
http://www.apexsql.com/sql_tools_diff.aspx
洙,
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)
可以使用SQL Management Studio中的工具‘生成脚本’从这两个数据库。然后使用您最喜爱的文本比较工具来查看任何差异。
在过去,这很好用,但在SQL 2005中,生成的脚本代码发生了变化,对象不再以相同的顺序创建,所以文本比较没那么有用。我还没有在更新版本的SQL中测试过它,所以它可能已经修复。您也可以尝试使用http://exportsqlscript.codeplex.com/,我已经很成功地将DDL用作源代码控制和比较版本的脚本。
参考文献:
当然,我最喜欢的文本比较工具是来自http://www.scootersoftware.com/ – 2010-10-18 19:08:52
Beyond Compare我尝试了确切的事情(生成脚本,我甚至用于比较)。不幸的是,正如您的文章所述,由于订购而失败...... – sooprise 2010-10-18 21:05:52
http://exportsqlscript.codeplex.com/确实解决了这个问题。而且,正如我向微软报告这个错误并在日志中所说的那样“它在下一个版本中已修复”。我从来没有见过微软的修复。 – 2010-10-20 13:44:27
你可以在http://cdttools.com/2011/10/sql-diff-erence/它的低成本替代看一看,会走两个数据库之间的模式,告诉你什么改变。然后,您可以使用SQL Mgmt studio生成“script-> As Alter”来构建更改脚本。 (警告:我写的)
如果在同一个数据库中的两个表,你可以使用这个查询
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')
我有点太迟了......但这个剧本我做了运作良好为了我。如果需要,它也可以跨链接服务器工作。
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
修改了一下的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
注:OP谈论结构,而不是数据。 – RedFilter 2010-10-18 18:56:01
@RedFilter:编辑了这个问题来澄清,这确实令人困惑 – 2010-10-18 18:57:47
当然,如果您编写脚本更改并将它们放在源代码管理中以便与该版本的软件的其余代码一起移动,它将会有所帮助。那么你不需要做所有这些差异(也可能意外地将一些尚未准备好的东西移动) – HLGEM 2010-10-18 19:13:34