数据库升级方案
一、面临的问题
在项目中数据库升级是经常遇到的事情,这个工作比较繁琐,特别是在线数据库升级需要十分小心,我们先来看一下通常面临的问题:
1、 表修改,包括增加了字段、修改了字段类型或者长度,更换了主键等。对于表的升级不能删除重建,需要单独修改,或者写脚本来升级。
2、 视图的修改,视图的修改比较简单,无非是增加了字段,取消了字段,不影响基础数据。视图的升级可以删除重建。
3、 存储过程的修改,存储过程的修改和视图一样,可以删除重建,二者都可以通过脚本来完成。
4、 函数的修改,如果项目中用到了函数,函数的升级和存储过程一样,不再赘述。
5、 上述情况基本能涵盖了大部分的数据库升级的情景,这些工作可以在数据库管理工具中完成,也可编写脚本来完成。我想说的问题并不是这个,而是有时候我们不知道那个表,那个字段修改了,除非你每改一个地方都做好记录,尽管如此,在升级的时候也难免落下。
我们公司有一套开发平台、由此平台开发了一套进销存,一套oa系统,而进销存又延伸出两套行业版进销存:鞋服通和医药通,以上产品有兴趣的可以去官网www.hfbpm.com试用,产品线如下图:
数据库和基础功能都是继承的,即进销存使用开发平台中的表,医药通和鞋服通使用通用进销存中的表,oa使用开发平台中的表,那么它们之间的数据库升级就非常频繁,刚开靠手工记录改动的地方,针对性的升级,后来发现工作量非常大,而且经常出错。
有没有一个一劳永逸的办法,比较差异进行数据库升级?只要思想不滑坡办法总比困难多!
办法肯定是有的。
二、解决方案
要解决数据库升级,主要是解决针对表、视图、存储过程函数的升级,后面三个相对来说比较简单,直接删除重建即可,难点是如何获取三者的创建脚本?只要获取到完整的脚本,当做sql语句执行即可,mssqlServer也给出了方法(下面会具体介绍)。表的升级相对来说要麻烦一些,因为表不能删除重建,必须对列、主键、约束等逐项进行比较升级,对于新建的表没有提供获取创建表脚本的方法,需要自己来处理。
下面详细介绍升级过程。
1、 表创建
MsSqlServer没有提供获取创建表脚本的方法,需要自己根据列属性生成创建脚本,为此我们编写了一个存储过程Sys_TableScript_MSSQL来做这件事情,存储过程的代码如下图:
由于篇幅限制,详细代码就不贴出来了,这个方法也是从博客园里收到的,稍微改动了一下,执行后输出的结果如下:
获取的是一个完整的创建表的脚本,该脚本当做普通的sql语句执行即可。
2、表升级
当表已经存在时,针对列进行升级,如果列不存在直接创建,如果列存在,那么是否升级判断依据是长度、类型、小数点位数、允许为空、默认值是否发生改变,上述只要有其一发生变化就要升级。
创建列的sql脚本,如下:
ALTER TABLE 表名 ADD 列名 类型 not null default '默认值'
例如
ALTER TABLE dx_ZhiBan ADD leaderName varchar(50) not null default '未填'
如果列已经存在需要使用修改列的sql脚本,如下:
ALTER TABLE 表名 alter column 列名 类型 not null
例如
alter table dx_ZhiBan alter column Leader nvarchar(50) not null
修改列时如果修改默认值,修改列的脚本不支持直接修改默认值,因为列一旦创建了默认值,那么就创建了一个约束,需要先删除这个约束,再重新创建默认值。删除默认值约束需要先找到默认值约束的名字,再执行删除约束脚本。查找默认值约束的sql脚本如下:
select c.name from sysconstraints a inner join syscolumns b on a.colid=b.colid inner join sysobjects c on a.constid=c.id where a.id=object_id('表名') and b.name='列名'
找到约束的名字如下图:
删除默认值约束的sql脚本如下图:
alter table 表名 drop constraint 默认值约束名
例如:
alter table dx_ZhiBan drop constraint DF__dx_ZhiBan__Leade__3FE65219
删除默认值后,再执行创建默认值的sql脚本,如下:
alter table 表名 add default '默认值' for 列名 with values
例如:
alter table dx_ZhiBan add default '未填' for Leader with values
表的升级除了列还包括主键,主键的升级和默认值类似(因为他们都属于约束),需要先删除原来,再创建新的。查找主键约束的sql脚本如下:
Select name from sysobjects where Parent_Obj=OBJECT_ID('表名') and xtype='PK'
例如:
Select name from sysobjects where Parent_Obj=OBJECT_ID('dx_ZhiBan') and xtype='PK'
查找结果如下:
删除主键约束的sql脚本如下:
Alter table dx_ZhiBan Drop PK_dx_ZhiBan
创建主键的sql脚本如下:
ALTER TABLE dx_ZhiBan ADD PRIMARY KEY (ID, leader )
注意,联合主键用逗号分隔,另外,需要说明的是在升级之前要判断主键是否需要升级,如果主键没有变化就不需要升级。
3、视图升级
视图升级过程较简单,删除掉重新创建即可。删除视图的sql脚本如下:
drop view 视图名
获取视图创建脚本的sql脚本,如下:
EXEC sp_helptext @objname='视图名称'
执行后结果如下图:
获取到该脚本后,当做普通的sql语句执行即可。
4、存储过程、函数升级
二者的升级和视图类似,不再赘述,不同的是删除存储过程的sql脚本是:
drop procedure 存储过程名
删除函数的sql脚本是:
drop function 函数名
5、数据库升级工具
数据库的升级是都能通过sql脚本来完成的,把这些脚本管理起来需要借助程序来完成,我们使用net的WinForm来编写程序。如下图:
使用这个工具可以选择那些对象需要升级(没有勾选的不升级),升级的时候能看到进度和升级结果。
本方案并不是十全十美的,有些问题还没解决,例如列名称修改、如何删除多余的列等。其他不当之处欢迎大家留言指正。