我必須在開發和發佈數據庫之間進行檢查,並手動執行此操作,這既緩慢又不是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