说明
基础的单表增删改查和左右连接,六大数据库完全一致,不再赘述。本文只记录有差异的语法点,按“基础常用”到“高级特性”排序。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)