Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL和达梦SQL语法差异

MySQL和达梦数据库SQL语法差异对比示例总结

作者:牛马爱开会

目前国内的很多领域大部分通用会使用到达梦数据库,这篇文章主要介绍了MySQL和达梦数据库SQL语法差异对比的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

在国内项目里,常见场景是:原来用 MySQL,后来要上国产数据库(如达梦 DM8/DM7);或者新项目要同时兼容两种数据库。

本文从“实战迁移”角度,系统梳理 MySQL 和达梦数据库在 SQL 语法上的差异,并用对照示例帮助你快速上手。

一、整体定位与兼容思路

实战建议:

  • 如果是从 MySQL 迁移到达梦,优先按“Oracle 风格”来写 SQL,更稳定、功能更全。
  • 纯应用开发中,尽量避免写死数据库特定语法(比如 LIMIT),用统一的 DAO/ORM 分页封装。

二、数据类型差异

2.1 数值类型对比

场景MySQL达梦(DM)备注
整型,主键INT, BIGINTINT, BIGINT, NUMBER(p)DM 里用 NUMBER 也很常见
浮点FLOAT, DOUBLEFLOAT, DOUBLE, NUMBER(p,s)建议改用 NUMBER(p,s) 控制精度
定点小数(金额)DECIMAL(p,s)DECIMAL(p,s)NUMBER(p,s)语义类似

示例:

MySQL 建表(金额字段):

CREATE TABLE order_info_mysql (
    id        BIGINT PRIMARY KEY AUTO_INCREMENT,
    amount    DECIMAL(18, 2),
    discount  FLOAT
);

达梦推荐写法:

CREATE TABLE order_info_dm (
    id        BIGINT PRIMARY KEY,
    amount    NUMBER(18, 2),
    discount  NUMBER(10, 4)
);

迁移时重点关注:DECIMAL/NUMBER 精度,避免金额、统计类字段精度丢失。

2.2 字符串类型对比

场景MySQL达梦(DM)备注
可变长度字符串VARCHAR(n)VARCHAR2(n)VARCHAR(n)达梦中更偏向 Oracle 风格 VARCHAR2
固定长度字符串CHAR(n)CHAR(n)基本一致
大文本TEXT, MEDIUMTEXT, LONGTEXTCLOB迁移时一般 TEXT → CLOB
二进制BLOB 系列BLOB名称类似

示例:

MySQL:

CREATE TABLE user_mysql (
    id       BIGINT PRIMARY KEY AUTO_INCREMENT,
    name     VARCHAR(50),
    bio      TEXT
);

达梦:

CREATE TABLE user_dm (
    id       BIGINT PRIMARY KEY,
    name     VARCHAR2(50),
    bio      CLOB
);

2.3 日期时间类型对比

场景MySQL达梦(DM)备注
日期DATEDATE都只保存日期
日期+时间DATETIME, TIMESTAMPTIMESTAMPDM 的 DATE 更接近 Oracle 的 DATE(含时间)视版本配置而定
当前时间函数NOW(), CURRENT_TIMESTAMPSYSDATE, SYSTIMESTAMP, CURRENT_TIMESTAMP迁移时重点是函数名差异

常见写法对比:

MySQL:

SELECT NOW(), CURDATE();

达梦:

SELECT SYSDATE, CURRENT_DATE FROM DUAL;

三、自增主键与序列

这是从 MySQL 迁移到达梦时最常踩坑的地方之一。

3.1 MySQL:AUTO_INCREMENT

CREATE TABLE user_mysql (
    id   BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50)
);

插入时可以不写 id

INSERT INTO user_mysql (name) VALUES ('Tom');

3.2 达梦:IDENTITY 或 SEQUENCE

达梦有两种常用方案:

  1. IDENTITY(类似自增):
CREATE TABLE user_dm_identity (
    id   BIGINT IDENTITY(1,1) PRIMARY KEY,
    name VARCHAR2(50)
);

插入:

INSERT INTO user_dm_identity (name) VALUES ('Tom');
  1. SEQUENCE + 触发器/应用赋值(Oracle 风格)
CREATE SEQUENCE seq_user_dm
    START WITH 1
    INCREMENT BY 1;

CREATE TABLE user_dm (
    id   BIGINT PRIMARY KEY,
    name VARCHAR2(50)
);

应用层插入(典型写法):

INSERT INTO user_dm (id, name)
VALUES (seq_user_dm.NEXTVAL, 'Tom');

实战建议:

  • 新项目尽量使用 IDENTITY 简化开发;
  • 如需跨表统一主键生成,适合用 SEQUENCE,并统一封装在 DAO 层。

四、分页查询写法差异

4.1 MySQL:LIMIT 语法

SELECT * FROM user_mysql
ORDER BY id
LIMIT 10 OFFSET 20;  -- 从第21行开始,取10行

或:

SELECT * FROM user_mysql
ORDER BY id
LIMIT 20, 10;        -- 同样效果

4.2 达梦(Oracle 风格):ROWNUM 或窗口函数

标准 SQL + Oracle 风格两种常用写法。

写法一:ROWNUM 双层子查询

SELECT *
FROM (
    SELECT u.*, ROWNUM AS rn
    FROM user_dm u
    ORDER BY u.id
) t
WHERE t.rn > 20 AND t.rn <= 30;

写法二:窗口函数 ROW_NUMBER()

SELECT *
FROM (
    SELECT u.*, ROW_NUMBER() OVER (ORDER BY u.id) AS rn
    FROM user_dm u
) t
WHERE t.rn > 20 AND t.rn <= 30;

提示:

  • ORM(如 MyBatis、JPA)一般都有“分页方言”配置,把 LIMIT 自动转换为对应数据库语法。
  • 若自己拼 SQL,建议在 DAO/Repository 层封装统一分页接口。

五、字符串与日期函数差异

5.1 常用字符串函数对比

功能MySQL达梦(DM)
字符串长度LENGTH(str)(字节), CHAR_LENGTH(str)(字符)LENGTH(str)(字符)
子串SUBSTRING(str, pos, len)SUBSTR(str, pos, len)
拼接CONCAT(a, b, ...)CONCAT(a, b) 或 字符串拼接符 `
查找位置INSTR(str, substr)INSTR(str, substr)
大小写UPPER(str), LOWER(str)UPPER(str), LOWER(str)

示例对比:

MySQL:

SELECT CONCAT(first_name, ' ', last_name) AS full_name
FROM user_mysql
WHERE INSTR(name, 'Tom') > 0;

达梦:

SELECT first_name || ' ' || last_name AS full_name
FROM user_dm
WHERE INSTR(name, 'Tom') > 0;

迁移时重点替换:CONCAT 多参数 → 使用 || 或多层嵌套 CONCAT

5.2 日期格式化与解析

示例对比:

MySQL:

SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s') AS now_str;

达梦:

SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS now_str
FROM DUAL;

MySQL 插入字符串日期:

INSERT INTO logs_mysql (create_time)
VALUES (STR_TO_DATE('2024-01-01 10:20:30', '%Y-%m-%d %H:%i:%s'));

达梦:

INSERT INTO logs_dm (create_time)
VALUES (TO_DATE('2024-01-01 10:20:30', 'YYYY-MM-DD HH24:MI:SS'));

六、空值判断与条件函数

6.1 空值判断函数

示例:

MySQL:

SELECT IFNULL(nickname, '匿名') AS nick
FROM user_mysql;

达梦:

SELECT NVL(nickname, '匿名') AS nick
FROM user_dm;

6.2 条件表达式

MySQL:

SELECT
    IF(status = 1, '启用', '禁用') AS status_name
FROM user_mysql;

达梦(推荐):

SELECT
    CASE WHEN status = 1 THEN '启用' ELSE '禁用' END AS status_name
FROM user_dm;

达梦(DECODE):

SELECT
    DECODE(status, 1, '启用', '禁用') AS status_name
FROM user_dm;

实战建议:为减少多库差异,统一使用 CASE WHEN,MySQL 和达梦都支持。

七、系统表与元数据查询差异

在运维、代码生成、自动建模时,经常会查询“表结构信息、索引信息”。

7.1 查看所有表

SHOW TABLES;
SELECT TABLE_NAME
FROM USER_TABLES;

查看所有可见表:

SELECT OWNER, TABLE_NAME
FROM ALL_TABLES;

7.2 查看表结构

DESC user_mysql;
-- 或
SHOW COLUMNS FROM user_mysql;
SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, NULLABLE
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'USER_DM';

提示:达梦的元数据视图设计几乎与 Oracle 一致,可以直接套用大量 Oracle 的管理经验。

八、事务与锁:语义类似,但默认行为不同

8.1 基本事务语法

MySQL 与达梦的事务控制语法基本一致:

-- 开启事务(MySQL + InnoDB & 达梦)
START TRANSACTION;

UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;

COMMIT;  -- 或 ROLLBACK;

8.2 差异点提示

迁移时常见问题:

  • 插入/更新时违反外键、唯一约束,在 MySQL 被默认忽略或以 Warning 形式出现;到了达梦会直接报错——需要在代码层真正处理异常、保证数据一致性。

九、索引与约束语法差异

9.1 唯一约束与唯一索引

MySQL:

CREATE TABLE user_mysql (
    id     BIGINT PRIMARY KEY AUTO_INCREMENT,
    email  VARCHAR(100) UNIQUE
);

CREATE UNIQUE INDEX idx_user_email
ON user_mysql (email);

达梦:

CREATE TABLE user_dm (
    id     BIGINT PRIMARY KEY,
    email  VARCHAR2(100),
    CONSTRAINT uk_user_email UNIQUE (email)
);

CREATE UNIQUE INDEX idx_user_email
ON user_dm (email);

达梦更推荐显式命名约束CONSTRAINT xxx),便于后期变更和管理。

9.2 外键约束

写法基本一致,但达梦会更严格地执行外键检查。

MySQL:

CREATE TABLE order_mysql (
    id         BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id    BIGINT,
    CONSTRAINT fk_order_user
        FOREIGN KEY (user_id) REFERENCES user_mysql(id)
);

达梦:

CREATE TABLE order_dm (
    id         BIGINT PRIMARY KEY,
    user_id    BIGINT,
    CONSTRAINT fk_order_user
        FOREIGN KEY (user_id) REFERENCES user_dm(id)
);

十、常见 SQL 场景对照示例(汇总版)

这一节给出常用业务场景的“完整对照”,方便直接复制对比。

10.1 按条件分页查询用户列表

MySQL 写法:

SELECT id, name, age
FROM user_mysql
WHERE age >= 18
ORDER BY create_time DESC
LIMIT 20, 10;

达梦写法(ROW_NUMBER 分页):

SELECT *
FROM (
    SELECT
        u.id,
        u.name,
        u.age,
        ROW_NUMBER() OVER (ORDER BY u.create_time DESC) AS rn
    FROM user_dm u
    WHERE u.age >= 18
) t
WHERE t.rn > 20 AND t.rn <= 30;

10.2 统计每天注册用户数(按日期分组)

MySQL:

SELECT
    DATE_FORMAT(create_time, '%Y-%m-%d') AS dt,
    COUNT(*) AS cnt
FROM user_mysql
GROUP BY DATE_FORMAT(create_time, '%Y-%m-%d')
ORDER BY dt;

达梦:

SELECT
    TO_CHAR(create_time, 'YYYY-MM-DD') AS dt,
    COUNT(*) AS cnt
FROM user_dm
GROUP BY TO_CHAR(create_time, 'YYYY-MM-DD')
ORDER BY dt;

10.3 根据状态分类统计(条件表达式)

MySQL:

SELECT
    SUM(IF(status = 1, 1, 0)) AS active_cnt,
    SUM(IF(status = 0, 1, 0)) AS inactive_cnt
FROM user_mysql;

达梦(推荐 CASE WHEN 写法):

SELECT
    SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS active_cnt,
    SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) AS inactive_cnt
FROM user_dm;

十一、迁移与多库兼容的实战建议

十二、总结

到此这篇关于MySQL和达梦数据库SQL语法差异对比总结的文章就介绍到这了,更多相关MySQL和达梦SQL语法差异内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文