达梦数据库与程序兼容性验证

达梦数据库与程序兼容性验证

以下是***应用中出现的两个数据库不一致的地方。

  1. 不支持utf8mb4编码
    某些列需要支持录入emoj表情,所以需要编码为utf8mb4,但是达梦数据库不支持该编码。

解决方案:可在建表时将该列的数据类型,指定为Text,需要正确统计数据库中所有需要指定为Text类型的列。

注意:text类型的字段,在select时,需要进行to_char()函数转换,否则显示错误。如select id,content from table,应写为select id, to_char(content) content from table.

  1. 大小写敏感问题
    为了避免sql语句中的所有别名都增加双引号,数据库迁移时指定了大小写不敏感,这样会造成sql语句的返回结果集的列明全部都是大写,程序中存在大量返回类型为List类型的接口,Map的key区分大小写,会造成本来数据库中存在的数据值,返回结果却为空。

解决方案:自定义HashMap子类,重写get、containKey等方法。

需要分情况替换mapper、service、controller以及其他类中的HashMap,主要依据mapper的返回值进行其他相关代码的修改。

先批量替换xml文件中的resultType=“java.util.HashMap”为resultType=“自定义map类全路径”;
批量替换mapper中的返回值 List 为List<自定义map>,批量替换import java.util.HashMap为import 自定义Map,若原代码确实需要引入HashMap,再重新引入;
批量替换service中的返回值为 List 为List<自定义map>;
批量替换controller中的返回值。
另外,数据库字段全部大写后,需要检查返回前端的数据格式是否发生变化。例如,有的直接将map转换成json后直接返回前端了。

解决方案:需要对map的数据进行转换或返回List数据格式替代List,保证按照原数据格式返回前端。

需要修改的接口有:

/getWishList.do

/getContactUserByKeys.do

/getForumOperList.do

/getForumComment.do

/contactDeptsModified.do(作废)

  1. base64加密/解密函数
    不能用mysql的from_base64()和to_base64()函数。

解决方案:采用系统包UTL_I18N、UTL_ENCODE,示例如下:

对“lily”加密如下:

UTL_I18N.RAW_TO_CHAR(UTL_ENCODE.BASE64_ENCODE(UTL_I18N.STRING_TO_RAW(‘lily’,‘UTF8’)))或

UTL_I18N.RAW_TO_CHAR(UTL_ENCODE.BASE64_ENCODE(UTL_I18N.STRING_TO_RAW(‘lily’)))

加密结果:bGlseQ==

对lily加密后的字符串进行解码:

select UTL_I18N.RAW_TO_CHAR(UTL_ENCODE.BASE64_DECODE(UTL_I18N.STRING_TO_RAW(‘bGlseQ==’)))

  1. Sql语句前是否需要增加模式名
    解决方案:为避免每个sql语句访问时不添加模式名,需要:

数据库用户名=模式名。

  1. Where子句中不支持case when
    Where子句中的case when语句,需要修改,用and or方案。

  2. case when 。。。 else 。。。 end
    case when 。。。 else 。。。 end 语句中包含函数运算时,是对整个结果集进行函数运算,要实现对空数据、非空数据进行不同的处理时可能会报错,如:再对publicTo进行函数运算时,原则上应该是分两种情况,(1)publicTo为空时;(2)publicTo不为空时;

select publicTo, case when publicTo = ‘’ or publicTo IS NULL then ‘’ else UTL_ENCODE.BASE64_DECODE(UTL_I18N.STRING_TO_RAW(publicTo)) end publicTo1

     from forum_comment  where releaseId = 4777;

     select distinct publicTo from forum_comment where releaseId = 4777;

下面这条数据publicTo数据不为空,才不报错,因为所有的结果集中publicTo都不为空:

     select publicTo, case when publicTo  = '' or publicTo IS NULL then '' else UTL_ENCODE.BASE64_DECODE(UTL_I18N.STRING_TO_RAW(publicTo)) end publicTo1

     from forum_comment where ID =3928;

解决方案:

如果是insert语句,可以增加条件判断,如:

INSERT INTO table(publicTo)

    VALUES

      <choose>

          <when test="forumComment.publicTo = null or forumComment.publicTo = ''">

              ''

          </when>

          <otherwise>                  

              UTL_I18N.RAW_TO_CHAR(UTL_ENCODE.BASE64_ENCODE(UTL_I18N.STRING_TO_RAW(#{forumComment.publicTo})))

          </otherwise>

      </choose>

如果是select语句,用000000000不可能出现的字符串替代转换,再将结果’MDAwMDAwMDAw’替换为空串。如:

replace(UTL_I18N.RAW_TO_CHAR(UTL_ENCODE.BASE64_ENCODE(UTL_I18N.STRING_TO_RAW(case when publicTo == ‘’ OR publicTo is null then ‘000000000’ else publicTo end))),‘MDAwMDAwMDAw’,‘’)

  1. 不支持Insert into on duplicate key update
    用merge into语句替换,但sql较长,并且using中的子表中每一列都要起别名。

  2. 不支持group_concat()函数
    group_concat()函数,需替换为wm_concat或者listagg() within group(order by )语句,wm_concat()仅是将多个结果连接为一个字符串,如果需要排序或分隔符,就需要替代为 listagg within group函数。如需要将通讯地址以“|,”分隔的话,就需要替换为

(select listagg(address,‘|,’) WITHIN GROUP (order by shOrder asc) from contact_dept_addr where deptid = d.addrDeptId )

  1. 日期计算INTERVAL
    日期函数date_sub(now(),INTERVAL 7 DAY) 需替换为date_sub(now(),INTERVAL ‘7’ DAY)

  2. 不支持insert ignore into
    insert ignore into 替换为 merge into

修改状态:暂未替换,比较繁杂,暂时去掉了ignore

  1. 不支持replace into
    replace into 替换为 merge into

修改状态:暂未替换,比较繁杂,需要修改的地方也较多

  1. tinyint类型数据返回不一致
    tinyint类型数据返回不一致,columnValue=“1”,mysql返回true,达梦返回1。

  2. 不支持count distinct后面跟多列
    count distinct 后面不能跟多列,只能一列,即 select count(distinct userId, userName) from contact_user报错

解决方案:select count(*) from (select distinct userId,userName from …)) a

  1. md5()函数返回不一致
    md5()函数加密后的值与mysql加密后的值不同,前者加密后是十六进制数。

解决方案:to_char(md5(‘123’))

  1. 建表语句是否要去带模式名?模式名、表名、列名是否需要带双引号?是否需要带storage参数?
    回复:不需要。

  2. 批量insert时存在自增序列的字段
    如insert into user_info_list_history select * from user_info_list,其中p_id字段是自增序列,需要进行两项修改:

一是insert前需要设置目标表的自增序列字段允许插入值,而不是系统处理,这个修改比较简单;

二是要显示指明要插入目标表的各个字段,即:

set IDENTITY_INSERT user_info_list_history on;

insert into USER_INFO_LIST_HISTORY(USERACCOUNT, USERNAME, USERID, DEPTID, DEPTNAME, OAPASS, YWQX, P_ID, MAINDEPTID, FACECHECKFLAG, IFASKITSYSFORLEAVE, PY, LEAVELAUNCHSYSFLAG, USERORDER, OPERTIME)

select * from user_info_list ;

set IDENTITY_INSERT user_info_list_history off;

这一项比较麻烦,需要做很多个性化处理,每个表的字段都不同。

  1. 使用mybatis批量insert一个List报错
    对于如下形式的批量数据库插入操作:

insert into table(column1,column2,…columnN)

List的size不超过8000时,就会报错:nested exception is dm.jdbc.driver.DMException: 第95258 行附近出现错误:

超过最大参数个数(32767)。

回复:目前无法解决,只能将list拆成多个,分次insert。

  1. 数据库性能较差
    批量插入上万条数据,性能较差,如:

insert into approve_record select * from approve_record_history_2018

同样插入339,132条记录,达梦数据库使用了1分34秒,mysql数据库用了30.125秒,相差悬殊。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值