兩個數據庫比較 對比視圖存儲過程及表結構差異
一、視圖和存儲過程比較
【原理】利用系統表“sysobjects"和系統表“syscomments”,將數據庫中的視圖和存儲過程進行對比。系統表"sysobjects"之前有詳細介紹過,有興趣可以看看:SQL Server系統表sysobjects介紹與使用
【代碼】
/*--調用示例
exec
p_compdb 'DBNAME1','DBNAME2' exec
p_compdb 'DBNAME2','DBNAME3' --*/ CREATE proc
p_compdb @db1
sysname, --第一個庫
@db2
sysname --第二個庫
as exec ( '
select
類型=case isnull(a.xtype,b.xtype) when ' 'V' '
then ' '視圖' '
else ' '存儲過程' '
end ,匹配情況=case
when
a.name is null then ' '庫
[' +@db1+ ']
中無' '
when
b.name is null then ' '庫
[' +@db2+ ']
中無' '
else
' '結構不同' '
end ,對象名稱=isnull(a.name,b.name),a.text
as atext, b.text as btext from(
select
a.name,a.xtype,b.colid,b.text from
[' +@db1+ ']..sysobjects
a,[' +@db1+ ']..syscomments
b where
a.id=b.id and a.xtype in(' 'V' ',' 'P' ')
and a.status>=0 )a
full join( select
a.name,a.xtype,b.colid,b.text from
[' +@db2+ ']..sysobjects
a,[' +@db2+ ']..syscomments
b where
a.id=b.id and a.xtype in(' 'V' ',' 'P' ')
and a.status>=0 )b
on a.name=b.name and a.xtype=b.xtype and a.colid=b.colid where
a.name is null or
b.name is null or
isnull(a.text,' '' ')
<>isnull(b.text,' '' ')
--group
by a.name,b.name,a.xtype,b.xtype --order
by 類型,匹配情況,對象名稱' )
|
【執行結果】
二、數據表結構比較
【原理】利用系統表“sysobjects"、"sysindexes"、"sysindexkeys"、“syscomments”、"sysclumns"、"systypes"、"extended_properties",將數據庫中的表結構進行對比。(涉及到系統表比較多。就不一一介紹。直接上代碼。)
【代碼】
/*--比較兩個數據庫的表結構差異--*/ /*--調用示例
exec
p_comparestructure 'DBNAME1','DBNAME2' exec
p_comparestructure 'DBNAME2','DBNAME3' --*/ create proc
p_comparestructure @dbname1
varchar (250), --要比較的數據庫名1
@dbname2
varchar (250)
--要比較的數據庫名2
as create table #tb1(表名1
varchar (250),字段名
varchar (250),序號
int ,標識
bit ,主鍵
bit ,類型
varchar (250),
佔用字節數
int ,長度
int ,小數位數
int ,允許空
bit ,默認值
sql_variant,字段說明 sql_variant) create table #tb2(表名2
varchar (250),字段名
varchar (250),序號
int ,標識
bit ,主鍵
bit ,類型
varchar (250),
佔用字節數
int ,長度
int ,小數位數
int ,允許空
bit ,默認值
sql_variant,字段說明 sql_variant) --得到數據庫1的結構
exec ( 'insert
into #tb1 SELECT 表名=d.name,字段名=a.name,序號=a.colid,
標識=case
when a.status=0x80 then 1 else 0 end, 主鍵=case
when exists(SELECT 1 FROM ' +@dbname1+ '..sysobjects
where xtype=' 'PK' '
and parent_obj=a.id and name in ( SELECT
name FROM ' +@dbname1+ '..sysindexes
WHERE indid in( SELECT
indid FROM ' +@dbname1+ '..sysindexkeys
WHERE id = a.id AND colid=a.colid )))
then 1 else 0 end, 類型=b.name,佔用字節數=a.length,長度=a.prec,小數位數=a.scale,允許空=a.isnullable,
默認值=isnull(e.text,' '' '),字段說明=isnull(g.[value],' '' ')
FROM
' +@dbname1+ '..syscolumns
a left
join ' +@dbname1+ '..systypes
b on a.xtype=b.xusertype inner
join ' +@dbname1+ '..sysobjects
d on a.id=d.id and d.xtype=' 'U' '
and d.name <>' 'dtproperties' '
left
join ' +@dbname1+ '..syscomments
e on a.cdefault=e.id left
join sys.extended_properties g ON
a.ID=g.major_id
AND a.COLID=g.minor_id order
by a.id,a.colorder' )
--得到數據庫2的結構
exec ( 'insert
into #tb2 SELECT 表名=d.name,字段名=a.name,序號=a.colid,
標識=case
when a.status=0x80 then 1 else 0 end, 主鍵=case
when exists(SELECT 1 FROM ' +@dbname2+ '..sysobjects
where xtype=' 'PK' '
and parent_obj=a.id and name in ( SELECT
name FROM ' +@dbname2+ '..sysindexes
WHERE indid in( SELECT
indid FROM ' +@dbname2+ '..sysindexkeys
WHERE id = a.id AND colid=a.colid )))
then 1 else 0 end, 類型=b.name,佔用字節數=a.length,長度=a.prec,小數位數=a.scale,允許空=a.isnullable,
默認值=isnull(e.text,' '' '),字段說明=isnull(g.[value],' '' ')
FROM
' +@dbname2+ '..syscolumns
a left
join ' +@dbname2+ '..systypes
b on a.xtype=b.xusertype inner
join ' +@dbname2+ '..sysobjects
d on a.id=d.id and d.xtype=' 'U' '
and d.name <>' 'dtproperties' '
left
join ' +@dbname2+ '..syscomments
e on a.cdefault=e.id left
join sys.extended_properties g ON
a.ID=g.major_id
AND a.COLID=g.minor_id order
by a.id,a.colorder' )
--and
not exists(select 1 from #tb2 where 表名2=a.表名1) select 比較結果= case when a.表名1
is null and b.序號=1
then '庫1缺少表:' +b.表名2
when b.表名2
is null and a.序號=1
then '庫2缺少表:' +a.表名1
when a.字段名
is null and exists( select 1
from #tb1
where 表名1=b.表名2)
then '庫1
[' +b.表名2+ ']
缺少字段:' +b.字段名
when b.字段名
is null and exists( select 1
from #tb2
where 表名2=a.表名1)
then '庫2
[' +a.表名1+ ']
缺少字段:' +a.字段名
when a.標識
<>b.標識 then '標識不同' when a.主鍵
<>b.主鍵 then '主鍵設置不同' when a.類型
<>b.類型 then '字段類型不同' when a.佔用字節數
<>b.佔用字節數 then '佔用字節數' when a.長度
<>b.長度 then '長度不同' when a.小數位數
<>b.小數位數 then '小數位數不同' when a.允許空
<>b.允許空 then '是否允許空不同' when a.默認值
<>b.默認值 then '默認值不同' when a.字段說明
<>b.字段說明 then '字段說明不同' else '' end ,
*
from #tb1
a full join #tb2
b on a.表名1=b.表名2
and a.字段名=b.字段名
where a.表名1
is null or a.字段名
is null or b.表名2
is null or b.字段名
is null or a.標識
<>b.標識 or a.主鍵
<>b.主鍵 or a.類型
<>b.類型 or a.佔用字節數
<>b.佔用字節數 or a.長度
<>b.長度 or a.小數位數
<>b.小數位數 or a.允許空
<>b.允許空 or a.默認值
<>b.默認值 or a.字段說明
<>b.字段說明 order by isnull (a.表名1,b.表名2), isnull (a.序號,b.序號) --isnull(a.字段名,b.字段名)
go
|
【執行結果】
ps:以上SQL執行請採用系統管理員(sysadmin)角色賬號。其他角色我沒有試過,有時間可以嘗試一下。當我採用只映射了庫”owner"權限的賬號測試時,報如下錯誤:拒絕了對對象 'p_compdb' (數據庫 'master',架構 'dbo')的 EXECUTE 權限。
本文寫作時,採用的是SQL SERVER 2005版本,不保證其他版本也能正常運行。如其他版本有問題,可以留言,共同學習探討。調試環境明細如下:
Microsoft SQL Server Management Studio 9.00.1399.00
Microsoft Analysis Services 客戶端工具 2005.090.1399.00
Microsoft 數據訪問組件 (MDAC) 6.1.7600.16385 (win7_rtm.090713-1255)
Microsoft MSXML 3.0 4.0 6.0
Microsoft Internet Explorer 8.0.7600.16385
Microsoft .NET Framework 2.0.50727.4984
操作系統 6.1.7600