说明
基础的单表增删改查和左右连接,六大数据库完全一致,不再赘述。本文只记录有差异的语法点,按“基础常用”到“高级特性”排序。OceanBase 区分 Oracle 模式和 MySQL 模式,使用时需确认当前模式。
一、基础常用差异
1. 分页查询
| 数据库 | 写法 |
|---|
| Oracle 12c+ | OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY |
| MySQL | LIMIT 10 OFFSET 10 |
| SQL Server 2012+ | OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY |
| 达梦 | LIMIT 10 OFFSET 10(也支持 Oracle 的 OFFSET FETCH) |
| 人大金仓 | LIMIT 10 OFFSET 10 |
| OceanBase | MySQL模式用 LIMIT 10 OFFSET 10,Oracle模式用 OFFSET FETCH |
2. 自增主键
| 数据库 | 写法 |
|---|
| Oracle 12c+ | id NUMBER GENERATED BY DEFAULT AS IDENTITY |
| MySQL | id INT AUTO_INCREMENT PRIMARY KEY |
| SQL Server | id INT IDENTITY(1,1) PRIMARY KEY |
| 达梦 | id INT IDENTITY(1,1) PRIMARY KEY |
| 人大金仓 | id SERIAL PRIMARY KEY 或 IDENTITY |
| OceanBase | MySQL模式用 AUTO_INCREMENT,Oracle模式用序列 |
3. 字符串连接
| 数据库 | 写法 |
|---|
| Oracle / 达梦 / 人大金仓 | 'a' || 'b' |
| MySQL | CONCAT('a', 'b') |
| SQL Server | 'a' + 'b' |
| OceanBase | Oracle模式用 ||,MySQL模式用 CONCAT |
4. 获取当前时间
| 数据库 | 写法 |
|---|
| Oracle / 达梦 / 人大金仓 | SYSDATE |
| MySQL | NOW() |
| SQL Server | GETDATE() |
| OceanBase | Oracle模式用 SYSDATE,MySQL模式用 NOW() |
5. 空值处理
| 数据库 | 写法 |
|---|
| Oracle / 达梦 / 人大金仓 | NVL(col, '默认值') |
| MySQL | IFNULL(col, '默认值') |
| SQL Server | ISNULL(col, '默认值') |
| OceanBase | Oracle模式用 NVL,MySQL模式用 IFNULL |
所有数据库都支持通用标准写法:COALESCE(col, '默认值')
6. 字符串截取
| 数据库 | 写法 |
|---|
| Oracle / 达梦 / 人大金仓 | SUBSTR(str, start, length) |
| MySQL | SUBSTR(str, start, length) 或 SUBSTRING |
| SQL Server | SUBSTRING(str, start, length) |
| OceanBase | 两种模式都支持 SUBSTR / SUBSTRING |
二、进阶差异
7. 关联删除(根据另一个表的数据删除)
| 数据库 | 写法 |
|---|
| MySQL | DELETE t1 FROM t1 JOIN t2 ON t1.id = t2.id WHERE t2.status = 'expired' |
| Oracle / 达梦 / 人大金仓 | DELETE FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t1.id = t2.id AND t2.status = 'expired') |
| SQL Server | DELETE t1 FROM t1 JOIN t2 ON t1.id = t2.id WHERE t2.status = 'expired' |
| OceanBase | Oracle模式用 EXISTS,MySQL模式用 JOIN |
8. 关联更新(根据另一个表的数据更新)
| 数据库 | 写法 |
|---|
| MySQL | UPDATE t1 JOIN t2 ON t1.id = t2.id SET t1.name = t2.new_name |
| Oracle / 达梦 / 人大金仓 | UPDATE t1 SET name = (SELECT new_name FROM t2 WHERE t1.id = t2.id) WHERE EXISTS (SELECT 1 FROM t2 WHERE t1.id = t2.id) |
| SQL Server | UPDATE t1 SET t1.name = t2.new_name FROM t1 JOIN t2 ON t1.id = t2.id |
| OceanBase | Oracle模式用子查询,MySQL模式用 JOIN |
9. 插入时处理重复主键
| 数据库 | 写法 |
|---|
| MySQL | INSERT INTO t(id, name) VALUES(1, 'new') ON DUPLICATE KEY UPDATE name = 'new' |
| Oracle / 达梦 / 人大金仓 | MERGE INTO t USING dual ON (t.id = 1) WHEN MATCHED THEN UPDATE SET name = 'new' WHEN NOT MATCHED THEN INSERT (id, name) VALUES (1, 'new') |
| SQL Server | MERGE INTO t USING (SELECT 1 AS id) s ON t.id = s.id WHEN MATCHED THEN UPDATE SET name = 'new' WHEN NOT MATCHED THEN INSERT (id, name) VALUES (1, 'new') |
| OceanBase | Oracle模式用 MERGE,MySQL模式用 ON DUPLICATE KEY |
10. 类型转换
| 数据库 | 写法 |
|---|
| Oracle / 达梦 / 人大金仓 | TO_CHAR(date, 'YYYY-MM-DD')、TO_NUMBER('123')、TO_DATE('2026-06-20', 'YYYY-MM-DD') |
| MySQL | DATE_FORMAT(date, '%Y-%m-%d')、CAST('123' AS UNSIGNED)、STR_TO_DATE('2026-06-20', '%Y-%m-%d') |
| SQL Server | CONVERT(VARCHAR, date, 23)、CAST('123' AS INT)、CONVERT(DATETIME, '2026-06-20', 20) |
| OceanBase | Oracle模式用 TO_CHAR/TO_NUMBER/TO_DATE,MySQL模式用 DATE_FORMAT/CAST/STR_TO_DATE |
11. 日期运算
| 数据库 | 写法 |
|---|
| Oracle / 达梦 / 人大金仓 | SYSDATE + 7(7天后)、MONTHS_BETWEEN(d1, d2)(相差月份) |
| MySQL | DATE_ADD(NOW(), INTERVAL 7 DAY)、DATEDIFF(d1, d2)(相差天数) |
| SQL Server | DATEADD(DAY, 7, GETDATE())、DATEDIFF(DAY, d1, d2) |
| OceanBase | Oracle模式用 SYSDATE + N,MySQL模式用 DATE_ADD/DATEDIFF |
12. 表结构复制
| 数据库 | 写法 |
|---|
| Oracle / 达梦 / 人大金仓 | CREATE TABLE t_backup AS SELECT * FROM t |
| MySQL | CREATE TABLE t_backup LIKE t(仅结构)、CREATE TABLE t_backup AS SELECT * FROM t(结构+数据) |
| SQL Server | SELECT * INTO t_backup FROM t |
| OceanBase | Oracle模式用 CREATE TABLE ... AS SELECT,MySQL模式用 LIKE 或 AS SELECT |
13. 批量插入
| 数据库 | 写法 |
|---|
| MySQL / SQL Server / 达梦 / 人大金仓 | INSERT INTO t(col1, col2) VALUES (v1, v2), (v3, v4), (v5, v6) |
| Oracle(12c前) | 需用 INSERT ALL INTO t(col1, col2) VALUES (v1, v2) INTO t(col1, col2) VALUES (v3, v4) SELECT 1 FROM dual |
| Oracle 12c+ | 支持标准批量写法 |
| OceanBase | MySQL模式支持标准批量写法,Oracle模式12c+也支持 |
14. TRUNCATE 差异
| 数据库 | 特点 |
|---|
| MySQL | TRUNCATE 重置自增计数器,DELETE 不重置 |
| Oracle | TRUNCATE 是 DDL,不能回滚;DELETE 是 DML,可以回滚 |
| SQL Server | TRUNCATE 需要较高权限 |
| 达梦 / 人大金仓 | 与 Oracle 行为一致 |
| OceanBase | 与对应模式的行为一致 |
15. DELETE 和 UPDATE 带别名
| 数据库 | DELETE 带别名 | UPDATE 带别名 |
|---|
| MySQL | DELETE t1 FROM t1 WHERE t1.id = 1 | UPDATE t1 SET t1.name = 'new' WHERE t1.id = 1 |
| Oracle / 达梦 / 人大金仓 | DELETE FROM t1 WHERE id = 1(不需要别名) | UPDATE t1 SET name = 'new' WHERE id = 1 |
| SQL Server | 同 MySQL | 同 MySQL |
| OceanBase | 与对应模式的行为一致 | |
三、通用写法速记(跨数据库兼容)
| 操作 | 通用写法 |
|---|
| 关联删除 | DELETE FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE ...) |
| 关联更新 | UPDATE t1 SET col = (SELECT col FROM t2 WHERE ...) WHERE EXISTS (...) |
| 插入或更新 | MERGE INTO ... USING ... ON ... WHEN MATCHED ... WHEN NOT MATCHED ... |
| 空值处理 | COALESCE(col, '默认值')(所有数据库通用) |
| 分页(标准) | OFFSET ... ROWS FETCH NEXT ... ROWS ONLY(Oracle 12c+、SQL Server 2012+、达梦、金仓) |
| 分页(通用) | MySQL和OceanBase MySQL模式用 LIMIT ... OFFSET ...,其余用 OFFSET FETCH |
四、Oracle 老式写法(兼容但不推荐)
| 操作 | 老式写法 | 推荐写法 |
|---|
| 左连接 | WHERE t1.id = t2.id(+) | LEFT JOIN ... ON ... |
| 右连接 | WHERE t1.id(+) = t2.id | RIGHT JOIN ... ON ... |
达梦、人大金仓兼容这种老式写法,但新代码不建议使用。
整理完发现,最基础的增删改查和左右连接语法所有数据库都一致,差异集中在分页、自增主键、函数、类型转换、关联操作这几个领域。国产数据库大多做了 Oracle 或 MySQL 兼容,迁移成本比几年前低了很多,但关键业务建议实测一遍。供参考,也方便自己回头查阅。
所有评论(0)