求助:新旧数据库对比,自动生成更新语句。
情况是这样的
有旧数据库A,新数据库B
可不可以通过比较A B,发现A,B不同地方。然后自动生成 从数据库A升级到B的更新语句。
不能把B里面的数据删除掉重新建表。
不需要处理具体数据,只需要表结构,存储过程,函数。
[解决办法]
说得不太清楚?A,B是主键不同还是一整条记录不同?
[解决办法]
表结构比较:-------------------------------------------------------if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_comparestructure]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)drop procedure [dbo].[p_comparestructure]GO/*--比较两个数据库的表结构差异可以比较两个数据库的结构差异--邹建 2003.9(引用请保留此信息)--*//*--调用示例exec p_comparestructure '库1','库2'--*/create proc p_comparestructure@dbname1 varchar(250),--要比较的数据库名1@dbname2 varchar(250)--要比较的数据库名2ascreate 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 aleft join '+@dbname1+'..systypes b on a.xtype=b.xusertypeinner 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.idleft join '+@dbname1+'..sysproperties g on a.id=g.id and a.colid=g.smallid 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 aleft join '+@dbname2+'..systypes b on a.xtype=b.xusertypeinner 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.idleft join '+@dbname2+'..sysproperties g on a.id=g.id and a.colid=g.smallid 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.表名2when b.表名2 is null and a.序号=1 then '库2缺少表:'+a.表名1when 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 afull 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
[解决办法]
/*--数据结构比较 比较两个数据库中的视图/存储过程的结构(结构比较,不是功能比较)--邹建 2004.07(引用请保留此信息)--*//*--调用示例 --调用 exec p_compdb 'pubs','northwind'--*/create proc p_compdb@db1 sysname, --第一个库@db2 sysname --第二个库asexec('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)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.colidwhere 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.xtypeorder by 类型,匹配情况,对象名称')go
[解决办法]
建议楼主用一下这个工具 SQL DELTA。http://cqdxdown.ddvip.com:81/down/SQLDelta4.zip挺不错的。
[解决办法]
/* 原创:fcuandy 修改:bing110 功能:动态传入“表名,字段名,字段类型,默认值”四个字符串,根据新的字段名称和类型来创表表结构 不足:由于修改的表时候保留原来字段的数据,所以现在暂时还不能修改字段类型,创建的表中也不能创建索引,外键约束等功能 日期:2008-9-9 */ CREATE FUNCTION dbo.Split --自定义的拆分函数,用来装传入的字符串分隔成表 ( @ItemList VARCHAR(4000), @delimiter VARCHAR(10) ) RETURNS @IDTable TABLE (IndexID INT IDENTITY(1,1),Item VARCHAR(50)) AS BEGIN WHILE CHARINDEX(@delimiter, @ItemList)>0 BEGIN INSERT @IDTable SELECT LEFT(@ItemList,CHARINDEX(@delimiter,@ItemList)-1) SET @ItemList=STUFF(@ItemList,1,CHARINDEX(@delimiter,@ItemList),'') END INSERT @IDTable SELECT @ItemList RETURN END CREATE PROC P_Alter_Table @tb VARCHAR(100), --表名 @fieldsLists VARCHAR(1000), --字段列表 @fieldsTypeLists VARCHAR(1000), --字段类型列表,需要与字段列表一一对应 @DefaultValue VARCHAR(1000) --新增字段默认值,与字段一一对应 AS BEGIN DECLARE @sql VARCHAR(8000) DECLARE @sql1 VARCHAR(8000),@sql2 VARCHAR(8000),@Sql0 VARCHAR(8000) IF object_id(@tb,'u') IS NULL --若表不存在 BEGIN SELECT @sql=ISNULL(@sql + ',','') + '[' + a.Item + '] ' + b.Item +' Default '+CHAR(39)+ c.Item +CHAR(39) FROM dbo.Split(@fieldsLists,',') a INNER JOIN dbo.Split(@fieldsTypeLists,',') b ON a.IndexID=b.IndexID INNER JOIN dbo.Split(@DefaultValue,',') C ON a.IndexId=C.IndexId EXEC('CREATE TABLE [' + @tb + '](' + @sql + ')') END ELSE --若表存在 BEGIN SELECT @sql1='',@sql2='',@sql0='' SELECT @sql1=@sql1 + CASE WHEN Field IS NULL THEN '['+name+'],' ELSE '' END,--记录待删除列列表 @Sql0=@Sql0 + CASE WHEN Field IS NULL AND CDEFAULT <> 0 THEN (SELECT [NAME] FROM SYSOBJECTS WHERE ID=CDEFAULT) + ',' ELSE '' END, --记录待删除的默认值 @sql2=@sql2 + CASE WHEN Name IS NULL THEN '['+Field+'] ' + FType + ' Default '+CHAR(39)+ DValue + CHAR(39)+',' ELSE '' END --记录待新增列列表 FROM (SELECT [NAME],CDEFAULT FROM syscolumns WHERE id=object_id(@tb,'u')) a FULL OUTER JOIN ( SELECT b.Item Field,a.Item FType,c.Item DValue FROM dbo.Split(@fieldsLists,',') b INNER JOIN dbo.Split(@fieldsTypeLists,',') a ON a.IndexID=b.IndexID INNER JOIN dbo.Split(@DefaultValue,',') c ON a.IndexId=c.IndexId ) b ON name=Field SELECT @sql1=STUFF(@sql1,LEN(@sql1),1,''),@sql2=STUFF(@sql2,LEN(@sql2),1,''),@sql0=STUFF(@sql0,LEN(@sql0),1,'') IF LEN(@sql2)>0 EXEC('ALTER TABLE [' + @tb + '] ADD ' + @sql2) --先加原表中不存在的列 IF LEN(@Sql0)>0 EXEC('ALTER TABLE ['+ @TB+ '] DROP CONSTRAINT '+ @Sql0) --删除表中不需要字段的默认值 IF LEN(@sql1)>0 EXEC('ALTER TABLE [' + @tb + '] DROP COLUMN ' + @sql1) --再删除新传入结构中不需要的列 END END Eg: EXEC P_ALTER_TABLE 'A','A1,A2','INT,VARCHAR(10)','0,T' SELECT * FROM A
[解决办法]
如果还需要处理主健、索引、约束等,自己再连下系统表,处理一下。
[解决办法]
帮顶,即使是路过
[解决办法]
:)
[解决办法]
学习啊!都是高人啊
[解决办法]
学习
[解决办法]
学习
[解决办法]
我也有这样的需求,写一个脚本..
http://download.csdn.net/source/1157973
[解决办法]
study
[解决办法]
学习
[解决办法]
楼主的表达不是很清楚。查查merge语句,可能可以实现楼主的需求。
[解决办法]
有工具,下一个就可以了。
好像叫:SQLDelta
[解决办法]
mark
[解决办法]
VS2005,VS2008自带有数据库比较Schema的工具,可以看下,是不是你想要的啊!!
项目---创建项目---选择"数据库项目",可以选择2000/2005
VS2008可以支持SQL2008的,不过得装一个GDR工具包!
[解决办法]
mark up
[解决办法]
最完美解答:
如果是Oracle数据库,用PL/SQL Developer的 tools--Compare User Object 功能,可以对比两个数据库,对比的差异直接生成SQL。
[解决办法]
Using PowerDesigner, this tool provides function to compare difference with model to DB schema in database or model in model-repository, also it can generate alter scripts automatically.
any difficultities, please contact me at bestysq@126.com
[解决办法]
学习了
[解决办法]
没有看明白
[解决办法]
帮lz
顶一下!!
[解决办法]
mark
[解决办法]
阅读阅读,但都觉得lz最终的目的就是把B的结构复制到A而已,要不要想的那么复杂??? 小的菜鸟各位大侠不要笑话~
[解决办法]