SQL Server 对比数据库差异

一、视图和存储过程比较

【原理】利用系统表“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 类型,匹配情况,对象名称' )

【执行结果】

 SQL Server 对比数据库差异_第1张图片

二、数据表结构比较

【原理】利用系统表“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

【执行结果】

SQL Server 对比数据库差异_第2张图片

 ps:以上SQL执行请采用系统管理员(sysadmin)角色账号。其他角色我没有试过,有时间可以尝试一下。当我采用只映射了库”owner"权限的账号测试时,报如下错误:拒绝了对对象 'p_compdb' (数据库 'master',架构 'dbo')的 EXECUTE 权限。

转载于:https://www.cnblogs.com/MuNet/p/6638698.html

你可能感兴趣的:(SQL Server 对比数据库差异)