这几天把项目的存储过程从oracle迁移到了达梦8,记录一下心得。国产数据库做到这样,已经算很了不起了,跟oracle兼容性确实很高。
但还是有一些细节没做好,主要是出错提示不友好,另外一个网上的资料也很少,出问题不好定位。(达梦的错误码比较简单,就是一个负数,不像oracle是ora-错误码,在百度时输入一个负数搜索信息,跟一长串错误码搜索效率差很远)
准备工作:
1 达梦的数据库管理工具默认不显示行号,也不能自动补全,需要手动设置。行号设置方法:在sql编辑页面,左侧空白竖栏(一般编辑器显示行号的地方)右击,选择”显示行号“。自动补全设置方法:在sql编辑页面空白处右击,选择“选项”,弹出的界面展开“查询分析器”,进入“编辑器”配置页面,选中“启用SQL输入助手”
2 装完达梦数据库后,需要启动oracle兼容模式sp_set_para_value(2,‘COMPATIBLE_MODE’,2);
,另外,需要启动dbms_job包,SP_INIT_JOB_SYS(1)。改完设置后记得重启。
迁移碰上的问题及解决方法:
1 使用达梦的数据库迁移工具,把oracle的用户整体迁移到达梦后,是变成一个模式,而不是用户,使用起来不方便。
解决方法:达梦数据库有用户和模式两个概念,库表和存储过程等是建在模式下面的,而用户则是独立的,与安全和权限功能挂钩,这跟mysql比较像。达梦的用户进行数据库操作时,默认使用同名的模式,想访问其它模式的元数据,需要显式加模式名。所以为了跟oracle保持一致,在迁移完后,需要手工给达梦添加oracle同名用户。
2 迁移后发现有一些存储过程,包等缺失。
解决方法:迁移工具做得不是太好,有一些oracle数据库的元素是不会自动迁移的,需要手工处理。例如oracle的type(达梦叫“类”),一些包含达梦数据库关键字的存储过程等。(在迁移日志里面没报错的,但也是可能没迁成功,需要仔细检查)
3 oracle建SEQUENCE里面的关键字MINVALUE达梦不支持
4 达梦的关键字比oracle多很多,例如CONTEXT,bool,class,decode这些,oracle不是关键字,但达梦是。
解决方法:给这些使用了关键字的字段名或者变量名加上"",并且转换成大写就可以了。例如"CLASS"
5 建了包,提示创建成功,编译有错,但没有具体说明错误地方。
解决方法:可以在后面增加语句:alter package q$err_mgr compile;
6 提示“第3156 行附近出现错误[-3719]: 非法的基类名[DBMS_SQL]”
解决方法:首先确认DBMS_SQL包是否启用(在左侧“工具包”菜单右键,选择启用)。如果启用了后还报这个错,则需要检查是否使用了某些DBMS_SQL的类型或者函数,在oracle有,但是在达梦没有的。
7 编译包时提示“第3494 行附近出现错误[-2193]:无效的方法名[func_name]"
解决方法:这种提示原因有很多,可能是确定在包里面没有定义这个func_name,也可能是func_name不在包头里面声明,但在初始化代码里面调用。(oracle允许只在包体里面定义,达梦不允许)。也可能是调用func_name的函数跟func_name都不在包头声明,但是在包体定义时,func_name出现位置比调用处更晚,在达梦这种是不允许的。
8 regexp系统函数提示“参数不兼容”
解决方法:达梦的regexp系统函数的参数名与oracle的不一样,如果原来在oracle指定了参数名,搬到达梦编译时容易出现这个错。改为非显示命名函数参数就好。
9 出现提示“第646 行附近出现错误[-3325]:包/对象[package_name]解析失败”,但646行代码是空白行
解决方法:达梦的报错位置不是太准确,这种情况下一般是上下文语法解析出现问题导致的。我碰到比较多的情况是在for循环语句里面使用了case when ... end子句。达梦8对于case when支持不太好,容易把case when的end关键字与begin配对了,导致语法错乱。我的解决方法是使用decode改写case when
10 报错提示“无法解析的成员访问表达式[XXX] ”
解决方法:这类错误主要是因为其它包之类的编译失效导致,需要具体分析再解决。有时会出现循环引用的情况(a包引用b包的函数,b包引用a的函数),达梦支持不太好,编译a时提示b的函数有问题,编译b时提示a的函数有问题。我的解决方法是建立一个c包,把一些代码从a和b抽出来,避免循环引用。大部分时候循环引用是可以编译过的,也可能是由于其它错误引起包编译不过,但是系统没提示好。这种情况下只要解决了另外的错误,这个循环引用编译失败的问题也就解决了。
11 提示“非法的基类名[ROWID]”
解决方法:我的代码里面使用了rowid类型变量,我直接改成number了
12 达梦对于重载(覆盖)支持不太好
解决方法:oracle里面两个同名函数,参数一样,只是一个是IN类型参数 ,一个是IN OUT参数,是被认为是两个不同类型的函数,可以正常重载。但达梦认为是同一个函数,编译时会出错。解决办法是把其中一个改名。另外,oracle里面varchar2(64),varchar2(1024)是两种不同的类型,可以支持重载两个函数,参数为这两种类型,但在达梦不支持。oracle里面同名的CONSTANT变量定义,后出现的会覆盖先出现的。但在达梦里面不支持。提示“错误号: -2120 无效的变量名”
迁移过程中也许还会碰上其它问题,处理原则是查官方帮助文档(在帮助菜单下面搜索,同时在安装目录下面也有很多pdf文件介绍),查百度,问官方支持。(我另了达梦的技术支持群,群里的南网工作人员还是挺热心的)
有时官方支持也搞不清楚,需要自己通过删减代码,慢慢定位问题,再自己猜测出错原因并尝试解决。
另外,之前有人写过一份教程《oracle迁移达梦常见问题汇总》 https://www.cndba.cn/foucus/article/4142 ,里面介绍了不少迁移的经验,也是值得借鉴的。