面向已经熟悉 mysql,准备上手人大金仓(kingbasees)的开发者,用「对比 + 示例」的方式,帮助你快速迁移与排坑。
0. 适用人群与阅读收获
适用人群
- 有 mysql 使用经验的开发 / dba
- 正在把系统从 mysql 迁移到人大金仓
- 使用 mybatis / jpa 等 orm,但 sql 写得不少的同学
阅读完你将搞清楚:
- 人大金仓和 mysql 在库/模式、数据类型、自增主键、分页、upsert等方面的主要差异
- mysql 常见写法在人大金仓中一一对应的改法
- 一份可以直接拿来用的迁移 checklist
- upsert是insert与update的结合语法,表示行存在时执行update,不存在时执行insert。执行upsert操作时必须指定完整的primary key的相关列信息。upsert语法支持带时间戳的数据写入和批量写入,其中的upsert谓词也可用insert来替代。
1. 整体认知:mysql vs 人大金仓
1.1 技术血统
mysql
- 自己的一套实现,语法上参考 sql 标准 + 自定义方言。
- 大量 mysql 专有语法,例如:
limit offset, size、auto_increment、engine=innodb等。
人大金仓(kingbasees)
- 高度兼容 postgresql。
- 很多写法与 postgresql 一致,例如:
serial、limit ... offset ...、||字符串拼接、on conflict等。
迁移心法:把人大金仓当作 “类 postgresql”,再对比 mysql,会好理解得多。
1.2 迁移重点关注点
- 标识符大小写与引号规则
- 库 / 模式(schema)结构差异
- 数据类型映射:
tinyint(1)、datetime等 - 自增主键:
auto_incrementvsserial/sequence - 分页、upsert、函数等 sql 语法差异
- 事务、锁与
group by等细节行为差异
2. 标识符与库/模式结构差异
2.1 标识符与大小写
mysql:
- 是否区分大小写与系统和配置相关(
lower_case_table_names)。 - 常用 反引号 ` 包裹标识符:
select * from `user`;
人大金仓:
- 未加引号的标识符会被自动转为小写。
- 标识符用 双引号 " " 包裹:
select * from "user";
典型坑:
-- 在人大金仓中执行
create table "user" (
id serial primary key,
name varchar(50)
);
-- 下面这句会报错:
select * from user; -- 实际表名是 "user",区分大小写
-- 正确写法:
select * from "user";
迁移建议:强烈建议统一使用全小写 + 下划线命名(如
user,order_detail),建表时不要加双引号,这样最省心。
2.2 库 / 模式(schema)结构
mysql:
- 结构为:
database -> table
create database app; use app; create table user (...);
人大金仓:
- 结构为:
database -> schema -> table - 和 oracle 的 schema 概念类似。
-- 创建数据库后,在其中再创建 schema
create schema app;
create table app.user (
id serial primary key,
name varchar(50)
);
select * from app.user;
迁移建议
- 原来 mysql 的多库,可以在人大金仓中使用「一个数据库 + 多个 schema」来承载。
- 应用配置中要么固定 schema,要么查询时写全名
schema.table。
3. 数据类型对比与迁移映射
3.1 常用类型对照表
| 功能 | mysql 类型 | 人大金仓推荐类型 | 说明 |
|---|---|---|---|
| 布尔 | tinyint(1) | boolean | 人大金仓有原生布尔 |
| 小整数 | tinyint | smallint | |
| 整数 | int / integer | integer | |
| 大整数 | bigint | bigint | |
| 浮点 | float | real / double | |
| 双精度 | double | double precision | |
| 定点数 | decimal(p,s) | numeric(p,s) | 几乎兼容 |
| 固定长度字符串 | char(n) | char(n) | |
| 变长字符串 | varchar(n) | varchar(n) | |
| 长文本 | text | text | |
| 日期 | date | date | |
| 日期时间 | datetime / timestamp | timestamp | 需注意时区 |
| 二进制大对象 | blob | bytea | |
| json | json / jsonb | 一般为 json 或 text | 视版本支持 |
3.2 布尔类型迁移(高频)
mysql 常见写法:
create table user (
id int primary key auto_increment,
is_valid tinyint(1) not null default 1
);
人大金仓推荐写法:
create table user (
id serial primary key,
is_valid boolean not null default true
);
- mysql 一般用
0/1表示布尔。 - 人大金仓用
boolean+true/false,查询结果可能显示为t/f或true/false。
迁移建议:
- 字段类型改为
boolean。- 代码中不要再写
if (is_valid == "1"),要改为布尔判断。
3.3 日期时间类型
mysql:
create table log (
id int primary key auto_increment,
created_at datetime not null
);
人大金仓:
create table log (
id serial primary key,
created_at timestamp not null
);
建议:若系统内部不处理多时区,优先使用
timestamp without time zone;如果业务有时区要求,则结合with time zone+ 统一时区策略。
4. 自增主键:auto_increment vs serial / 序列
4.1 mysql:auto_increment
create table user (
id int primary key auto_increment,
name varchar(50)
);
4.2 人大金仓:serial 写法(最常用)
create table user (
id serial primary key,
name varchar(50)
);
serial实际上是:integer字段 + 一个序列 + 默认值nextval()。
4.3 人大金仓:显式序列写法(更可控)
create sequence user_id_seq;
create table user (
id integer primary key default nextval('user_id_seq'),
name varchar(50)
);
4.4 插入时的使用
mysql:
insert into user(name) values ('tom');
人大金仓:
insert into user(name) values ('tom'); -- 同样可以省略 id
迁移建议:
- 把所有
auto_increment字段统一改为serial/bigserial。- 如果运维脚本依赖“序列名称”,则用显式
create sequence写法,名字统一。
5. ddl 差异:建表与改表
5.1 建表语法对比
mysql:
create table user (
id int auto_increment primary key,
name varchar(50) not null,
created_at datetime default current_timestamp
) engine=innodb default charset=utf8mb4;
人大金仓:
create table user (
id serial primary key,
name varchar(50) not null,
created_at timestamp default current_timestamp
);
对比说明:
- 人大金仓中没有
engine=...这种写法。 - 字符集一般在数据库级配置,建表时不写
charset=...。
5.2 修改字段类型、默认值
mysql 改字段类型:
alter table user modify column name varchar(100);
人大金仓改字段类型(标准 sql 风格):
alter table user alter column name type varchar(100);
设置 / 删除默认值:
-- 设置默认值 alter table user alter column created_at set default current_timestamp; -- 删除默认值 alter table user alter column created_at drop default;
迁移建议:
- 把
modify column/change column类语法改为alter column ... type。- 批量迁移脚本时可以用正则先替换关键字,再人工检查。
6. dml 差异:分页 & upsert 等
6.1 分页语法对比
mysql 两种写法:
-- 写法 1:标准 limit + offset select * from user order by id limit 10 offset 20; -- 写法 2:mysql 方言 select * from user order by id limit 20, 10; -- offset 20, size 10
人大金仓:只支持第一种
select * from user order by id limit 10 offset 20;
迁移建议:
- 所有
limit offset, size写法都要替换成limit size offset offset。- 特别注意 mybatis / xml 里的手写 sql 是否有
${offset}, ${size}这样的写法。
6.2 upsert:on duplicate key vs on conflict
mysql 写法:
insert into user(id, name) values (1, 'tom') on duplicate key update name = values(name);
人大金仓写法:
insert into user(id, name) values (1, 'tom') on conflict (id) do update set name = excluded.name;
on conflict (id):指定发生冲突的列(主键或唯一键)。excluded:关键字,表示“本次插入语句中的数据”。
迁移建议:
- 把
on duplicate key update系列统一改为on conflict (...) do update。- 如果表有多个唯一约束,需明确写冲突列或约束名。
6.3 update / delete 基本一致
mysql:
update user set name = 'tom2' where id = 1; delete from user where id = 1;
人大金仓:
update user set name = 'tom2' where id = 1; delete from user where id = 1;
人大金仓还支持 returning:
update user set name = 'tom2' where id = 1 returning *;
可以一条语句完成“更新 + 返回最新数据”。
7. 常用函数差异:字符串、日期时间、聚合
7.1 字符串函数对比
| 功能 | mysql 写法 | 人大金仓(类似 postgresql)示例 |
|---|---|---|
| 字符串拼接 | concat(a, b) | a || b or concat(a, b) |
| 字符串长度 | char_length(str) / length(str) | 同 |
| 去空格 | trim(str) | 同 |
| 子串 | substring(str, pos, len) | substring(str from pos for len) 也支持 substring(str, pos, len) |
拼接示例:
-- mysql select concat(first_name, ' ', last_name) as full_name from user; -- 人大金仓(推荐) select first_name || ' ' || last_name as full_name from user;
7.2 日期时间函数对比
| 功能 | mysql 示例 | 人大金仓 示例(类似 postgresql) |
|---|---|---|
| 当前时间戳 | now() | now() 或 current_timestamp |
| 当前日期 | curdate() | current_date |
| 日期加减 | date_add(date, interval 1 day) | date + interval '1 day' |
| 计算时间差(秒) | timestampdiff(second, t1, t2) | extract(epoch from (t2 - t1)) |
示例对比:
-- mysql:当前时间后 1 天 select date_add(now(), interval 1 day); -- 人大金仓:当前时间后 1 天 select now() + interval '1 day';
7.3 group by 语义差异
- mysql 在非严格模式下,允许:
select中出现的非聚合字段不在group by中。 - 人大金仓更接近 sql 标准:
- 非聚合字段必须出现在
group by中,否则报错或不允许。
- 非聚合字段必须出现在
示例:
-- mysql 可能运行通过,但语义不严格 select id, name, count(*) from user group by id; -- 人大金仓中建议写为 select id, name, count(*) from user group by id, name;
迁移建议:
- 对所有
group by语句进行一次“体检”,保证非聚合字段全部出现在group by中。- 避免依赖 mysql “按某字段分组,其他字段随便拿一条”的行为。
8. 索引与约束差异
8.1 主键 & 唯一约束
mysql:
create table user (
id int primary key auto_increment,
email varchar(100),
unique key uk_email (email)
);
人大金仓:
create table user (
id serial primary key,
email varchar(100),
constraint uk_email unique (email)
);
建议在人大金仓中显式命名
constraint,维护时更清晰。
8.2 普通索引
mysql:
create index idx_user_name on user(name);
人大金仓:
create index idx_user_name on user(name);
此外,人 大金 仓支持更多高级索引(表达式索引、部分索引等):
-- 表达式索引:对小写后的名称建立索引 create index idx_user_lower_name on user (lower(name));
对于经常使用
lower(name)查询的场景,表达式索引可以效能明显提升。
9. 事务与锁的注意点(简要)
两者都支持 acid 和 mvcc,但实现细节不同。
9.1 基本事务语法
两者大体一致:
begin; update user set name = 'tom' where id = 1; commit; -- 或回滚 rollback;
9.2 锁相关注意点
select ... for update在人大金仓中语义类似 postgresql:- 会对选中的行加排他锁,用于“读后更新”的场景。
- 高并发场景下:
- 建议在测试环境压测验证:长事务、批量更新、带
for update的语句是否存在死锁 / 长时间等待。
- 建议在测试环境压测验证:长事务、批量更新、带
实战建议:
- 避免在一个大事务里夹杂 ddl 操作。
- 复杂迁移脚本先在测试环境完整跑一遍,观察锁等待和执行计划。
10. 实战迁移步骤与 checklist
10.1 推荐迁移步骤
梳理对象
- 全量导出 mysql 的库、表、视图、存储过程、触发器、函数等信息。
- 对每张表的主键、自增策略、外键、唯一约束做一份清单。
类型与建表脚本转换
auto_increment->serial/bigserial或显式序列。tinyint(1)->boolean;datetime->timestamp。- 删除
engine=...、charset=...等 mysql 专有语法。
dml 与函数适配
- 分页:
limit size offset offset替换limit offset, size。 - upsert:
on duplicate key update替换为on conflict (...) do update。 - 日期函数:
date_add/timestampdiff等改为interval+extract组合。 - 字符串拼接:改为
||或继续用concat。
- 分页:
索引与约束整理
- 唯一约束、外键统一命名
constraint。 - 根据查询模式考虑表达式索引、组合索引。
- 唯一约束、外键统一命名
程序代码修改与联调
- orm 方言配置改为人大金仓 / postgresql。
- 检查所有手写 sql:分页、upsert、函数、group by。
压测与排错
- 高并发下验证事务隔离级别与锁等待。
- 对时间、时区、字符集相关逻辑做专项验证。
10.2 高频踩坑清单(可直接当项目 checklist)
- 是否还有
limit offset, size写法未替换? - 是否还有
auto_increment未改为serial/ 序列? - 布尔字段是否仍用
tinyint(1),代码中是否仍按"0"/"1"判断? - 是否有非标准
group by(select 中的非聚合字段未全部出现在 group by 中)? - 是否有 sql 依赖 mysql 非标准行为(如“分组后取任意一条记录”)?
- 是否有
on duplicate key update未替换为on conflict? - 是否有使用
date_add、timestampdiff、from_unixtime等函数未适配? - 表 / 字段名是否有大小写混用并加了双引号,在人大金仓中会非常“敏感”?
总结
到此这篇关于mysql和人大金仓数据库sql语法差异对比的文章就介绍到这了,更多相关mysql和人大金仓数据库sql语法对比内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论