今天做了一个数据库升级的工具,通过执行脚本来对数据库进行升级,这个工具也没有什么特殊的地方,但是却遇到了一个比较特殊的问题。
在数据库升级的时候,经常会遇到增加新表,视图等一些数据库常用的语句,由于需求规定了,每次版本的SQL语句要保存在程序中,而不是保存成一个SQL语句在数据库管理工具中直接执行,需求指导哪里,我们就要往哪里走,因此做的时候就按照需求的规定,做了一个借口,然后每次数据库的升级版本的类都继承该借口,同时通过装饰器(采用的是属性的形式来扩展的)方便的将新的版本加载到程序中,同时新的版本脱离主程序,在添加新版本的时候不会影响到原有的程序。
一切方案感觉上还是算是完美,为了节省系统同时保证一个唯一的实例,还用到了单例来保存连接服务的的信息,还有用到了观察者模式来确定当修改数据库的的时候,提示和列表的更新等,这一切看起来还是不错的,但是关键时刻出现了问题。
我将在SQL数据库管理工具中写好的语句放到当前版本的文件中,保存成一个字符串变量,然后通过程序执行,在数据库管理工具中用的好好的语句但是通过程序执行的时候就会报一个“GO附近有语法错误”的错误,这个让我百般不得其解,找来同事问究竟,也没有结果,后来一个同事百度,查找到了原因,说是生脚本的时候GO后面的char(10) char(13)只有char(10)了,因此SQL Server不认识, 这个不是愁人的事情么,没有办法,为了解决这个问题,开始了一番调试。
首先想到的是将只有char(10)的修改成char(10) char(13),在C#中,这个是比较容易做到的,做的时候,只需要将 "\n"的修改成"\n\r"就好用了,本意为做的天衣无缝的,但是在执行的时候还是报了错误......
这下真的头疼了,接下来我有用到了一个比较笨的办法,将里面的所有的GO都用好用的sql里面的Go将前面和后面的字符串都替换掉,但是又失败了...
在接下来,我干脆通过 Go 关键字来进行修改,将GO后面添加上 "\n\r",但是这样存在问题,如果某个字段里面恰恰有还有GO的字符,那就不成了,做太多的处理,不值得了吧...
最后采用了一个比较丑陋的办法,可以满足自己的要求,做法是这样的,由于添加视图或表之前要先判断是否存在,如果存在则删除,然后就GO一下,在创建,我就将这条语句分开执行,有点太丑陋的方法了,但是效果还可以,这样一来,就可以不用GO的关键字了,执行第一个语句的时候,如果存在,则删除,如果不存在,则不作处理,接下来之际创建表或视图就可以了,在也不用为那个GO的错误而烦恼了...
办法是有点破了点,这也是被逼无奈啊,都R2的版本了,这个问题SQL Service竟然当个宝是的还留着,咋就不解决一下呢,有时候这个破问题还不容易查找,还真以为脚本写错了呢……
如果在管理工具中在遇到这样的问题的时候,直接将问题的语句粘到记事本中,一看你就会明白了,为什么GO附近有错误,原来在记事本中显示的是 GO和其他的语句都连在一起了,听让人头疼的一件事情啊......
问题是解决了,不知道还有没有更好的办法……