zoukankan      html  css  js  c++  java
  • (转载) 两个数据库比较 对比视图存储过程及表结构差异

    一、视图和存储过程比较

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

    《一棵树-博客园》 收集整理,转载请注明出处!
  • 相关阅读:
    Ftp、Ftps与Sftp之间的区别
    Previous Workflow Versions in Nintex Workflow
    Span<T>
    .NET Core 2.0及.NET Standard 2.0 Description
    Announcing Windows Template Studio in UWP
    安装.Net Standard 2.0, Impressive
    SQL 给视图赋权限
    Visual Studio for Mac中的ASP.NET Core
    How the Microsoft Bot Framework Changed Where My Friends and I Eat: Part 1
    用于Azure功能的Visual Studio 2017工具
  • 原文地址:https://www.cnblogs.com/accumulater/p/6145562.html
Copyright © 2011-2022 走看看