sanmianti
sanmianti
发布于 2026-06-05 / 11 阅读
2

国产适配达梦数据库最佳实践

达梦数据库作为国产信创适配的首选数据库,其在项目中出现的频次越来越高。本文从注意事项、数据库部署初始化、数据迁移、应用数据库语法适配等维度阐述如何在项目实施过程中尽快落地实施,尽量少踩坑少走弯路。

特别注意事项

不同版本差异较大

达梦数据库不同版本之间差异较大,即使都是DM8,最好锚定一个具体的版本进行适配,不要随意改动。测试环境与生产环境要求大中小版本完全一致。

该篇文章基于 达梦V8 1-3-26-2023.07.13-195546-20046-ENT 版本撰写。

查看版本:SELECT * FROM SYS.V$INSTANCE

初始即信创

如果项目要上达梦数据库,最好一开始就用达梦数据库进行开发。不要想着先用MySQL凑合着然后在换数据库,后面使用MySQL迁移至达梦有很多需要返工的地方。风险较大。

数据库初始化

大小写敏感设置

基本概念

迁移数据前,需要确认大小写敏感,因为大小写敏感只能在初始化数据库的时候设置,默认为大小写敏感,一旦设置成功就无法修改,如果想要修改,只能重新初始化实例。

查询大小写是否敏感,结果为 1 是大小写敏感;结果为 0 是不敏感。

SELECT CASE_SENSITIVE();

大小写敏感: 表名,字段名,字段别名都自动转成了大写,且查询表中的数据时严格区分大小写。查询小写名时需要加双引号。

大小写不敏感: 表名,字段名,字段别名不会自动转成大写,且查询表中的数据时不区分大小写。

要求

本着最小改动的原则,由MySQL迁移至达梦时候达梦数据库应设置为大小写不敏感

字符集设置

数据库初始化时字符集选择  UTF-8

GLOBAL_CHARSET=0 表示使用的是 GB18030
GLOBAL_CHARSET=1 表示使用的是 UTF8

字符宽度设置

字符宽度选择1

LENGTH_IN_CHAR = 0 表示varchar/char类型的字段长度以字节为单位
LENGTH_IN_CHAR = 1 表示varchar/char类型的字段长度以字符为单位

注意!!!
LENGTH_IN_CHAR这个参数已经不支持了。迁移数据可以用迁移工具进行特殊处理了!

数据库兼容模式

建库选择MySQL兼容模式。

对于通过MySQL兼容模式来支持反引号这个功能,只有在8.1.3.37之后的版本中才支持,之前的版本只能去掉或者通过双引号。

关于这点有些版本支持反引号有些不支持。建议统一去掉反引号,用双引号是一个不错的选择。

查看兼容模式:

SELECT para_name, para_value FROM v$dm_ini WHERE para_name = 'COMPATIBLE_MODE';

数据库迁移

迁移策略选择

“保持对象名大小写”。字符长度放大倍数选4.0 (有些版本迁移后字符长度会默认扩大四倍。一定要提前确认好,否则可能会扩大 4x4倍)

char 特殊处理

从 MySQL 移植达梦,char 类型达梦会自动空格补齐。
迁移时char转换为varchar2类型。

数据库语法

单引号不能用于字段名别名

达梦中不允许使用单引号表示别名,单引号只能用于字符串常量。

下面SQL在达梦数据库中执行会报错:

 SELECT create_time AS 'createTime' FROM schema_name.table_name

正确写法:

 SELECT create_time AS createTime FROM 
schema_name.table_name

或

 SELECT create_time AS "createTime" FROM 
schema_name.table_name

GROUP_CONCAT表达式达梦不支持

使用 wm_concat 替代。

达梦join后面必须加ON条件

关联查询后面没有 ON 条件,这在 MySQL 中可能能容忍(默认笛卡尔积),但在 达梦中会直接语法报错。

关于label、value字段名的特殊处理(保留字)

查询时如果明确指定字段名,字段名中包含 label,value字段且未添加引号。则label、value字段会默认转换为大写。

查询语句

字段名返回值

SELECT value FROM table_name

VALUE

SELECT "value" FROM table_name

value

SELECT value,description FROM table_name

VALUE,description

SELECT description FROM table_name

description

SELECT xx AS value FROM table_name

VALUE

目前只遇到label、value字段有这种怪异行为。

关于order字段名的特殊处理(保留字)

order 是达梦数据库保留关键字。如果字段中有order字段,查询时字段名需要添加双引号。如果是 SELECT * 这种写法则不用特殊处理。

达梦保留关键字

object、order、value、label。查询时添加双引号。

反引号不被支持

字段名中不可用反引号,别名不可以用反引号。尽量全局都不要用反引号,除非经过测试能正常执行。

字段名别名不支持单引号

字段名别名中不可以用单引号,不可以用反引号。

数字与非数字字符串比较会报错

假设sys_user表中的user_id字段为Integer类型。则下属语法报错:

SELECT * FROM pig.sys_user WHERE  user_id = 'x43600' 
//-6111: 字符串转换出错

建议写法,添加正则判断条件

AND REGEXP_LIKE(#{userId}, '^[0-9]+$') 

自增主键兼容性问题

在MySQL中@GeneratedValue(strategy = IDENTITY) + insertSelective,这种写法可以生效。

但达梦数据库这种写法兼容性不佳,极易报错:

======= Sql Logger ======================
insert into sys_org_rel (id, org_code, parent_org_code, org_tree_type, org_seq) values (null, '3206130000000007', '3206130000000002', '02', 7)
======= Sql Execute Time: 0.817ms =======

2025-06-10 09:34:43,872 [XNIO-1 task-9] [1381929566821416960] ERROR [c.u.s.c.sentinel.handle.GlobalBizExceptionHandler] GlobalBizExceptionHandler.java:74 - 全局异常信息 ex=
### Error updating database.  Cause: dm.jdbc.driver.DMException: 仅当指定列列表,且SET IDENTITY_INSERT为ON时,才能对自增列赋值

建议使用 @TableId(type = IdType.AUTO),MySQL和达梦数据库都兼容。

达梦针对转义符执行严格标准

SELECT * FROM table_name WHERE name LIKE '%/华为%' ESCAPE '/';
该语句在MySQL执行正常,因为MySQL是宽容容错的。当转义符/后面不是特殊字符时,MySQL会默认忽略转义符/。

该语句在达梦数据库中执行报错:无效的转义字符。达梦要求转义符后面只能跟百分号%、下划线_、转义符自身,否则报错。

达梦不支持布尔表达式直接作为 COUNT 的参数

达梦数据库(Dameng DB)不支持 COUNT(<boolean expression> OR NULL) 这种写法。

COUNT(CASE WHEN ... THEN 1 ELSE NULL END) 是一种兼容大多数 SQL 数据库的条件统计方式。

库名、表名、字段名不支持中间横线、减号

达梦遵循 SQL 标准的标识符规则:必须以字母或下划线开头后面可以跟字母、数字、下划线不能包含 -、空格、特殊符号(除 _)

可以用双引号包裹。

库名表名如果以数字开头要添加双引号

库名表名如果以数字开头要添加双引号