两个数据库比较 对比视图存储过程及表结构差异
一、视图和存储过程比较
【原理】利用系统表“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