一、视图和存储过程比较
【原理】利用系统表“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