MySQL → Kingbase PG模式 高频SQL替换清单
适用:DB_MODE=pg(原生PG兼容模式),金仓V8/V9通用; 说明:金仓PG模式遵循PG语法,不再兼容mysql专属函数、语法、特殊值,下面是项目里最常碰到的,直接替换。
一、判空函数
| MySQL | PG(金仓) | 备注 |
|---|---|---|
IFNULL(col, val) |
COALESCE(col, val) |
推荐,标准SQL,支持多参数 COALESCE(a,b,c) |
NULLIF(a,b) |
NULLIF(a,b) |
通用,不用改 |
示例
-- mysql
select IFNULL(name,'未知') from t;
-- pg
select COALESCE(name,'未知') from t;
二、字符串聚合 GROUP_CONCAT
| MySQL | PG(金仓) |
|---|---|
GROUP_CONCAT(name SEPARATOR ',') |
STRING_AGG(name, ',') |
示例
-- mysql
SELECT GROUP_CONCAT(username SEPARATOR ',') FROM sys_user GROUP BY dept_id;
-- pg
SELECT STRING_AGG(username, ',') FROM sys_user GROUP BY dept_id;
注意:PG 默认会自动去重吗?不会,和GROUP_CONCAT默认一样;需要去重:
STRING_AGG(DISTINCT username, ',')
三、日期格式化 DATE_FORMAT
| MySQL | PG(金仓) |
|---|---|
DATE_FORMAT(ctime,'%Y-%m-%d %H:%i:%s') |
TO_CHAR(ctime,'YYYY-MM-DD HH24:MI:SS') |
格式对照重点
%Y→YYYY%m→MM%d→DD%H→HH24(24小时制) /HH12(12小时)%i→MI(分钟,不是MM!)%s→SS(秒)
示例
-- mysql
select DATE_FORMAT(create_time,'%Y-%m-%d') from t;
-- pg
select TO_CHAR(create_time,'YYYY-MM-DD') from t;
反向:字符串转日期
STR_TO_DATE('2026-10-21','%Y-%m-%d')→TO_DATE('2026-10-21','YYYY-MM-DD')
四、字符串截取 SUBSTRING_INDEX
MySQL:SUBSTRING_INDEX(str, delim, count),PG没有原生函数
-- mysql 取第一个分隔符前面:SUBSTRING_INDEX('a-b-c','-',1) → a
-- mysql 取最后一个分隔符后面:SUBSTRING_INDEX('a-b-c','-',-1) → c
PG实现方案:
-- 取第1段
split_part('a-b-c', '-', 1);
-- 取第3段
split_part('a-b-c', '-', 3);
短板:split_part 只能按序号取,不支持负数倒序 ;如果业务大量用到
-1取最后一段,需要自定义函数。
五、字符串拼接
| MySQL | PG |
|---|---|
CONCAT(a,b,c) |
CONCAT(a,b,c) |
| `a |
重点警告: MySQL里
select 1 || 2结果是1(逻辑or); PG里select 1 || 2是字符串拼接'12'。 如果老代码有||做判断,必须改成OR。
六、分页 LIMIT
| MySQL | PG |
|---|---|
LIMIT offset,size |
LIMIT size OFFSET offset |
-- mysql
select * from t limit 0,10;
-- pg
select * from t limit 10 offset 0;
七、布尔、0/1真假
MySQL:0=false,1=true PG:原生 boolean 类型 true / false; 如果用数字判断也支持,但推荐标准写法:
-- mysql where del_flag = 0
-- pg 建议:where del_flag is false
八、特殊日期:0000-00-00
MySQL 允许 0000-00-00 作为特殊零日期; 👉 PG模式完全不支持,直接报错 改造方案:
- 数据库字段改成可NULL;
- 业务用
NULL代替0000-00-00; - 代码里判断:日期为空展示"无"。
九、反引号 `````
MySQL标识符反引号 table PG模式:只能双引号 "table"
-- mysql
select `id`,`user_name` from `yz_sys_user`;
-- pg
select "id","user_name" from "yz_sys_user";
MyBatis:要么把反引号统一改成双引号;要么去掉标识符引号(名字无关键字时)
十、自增主键
MySQL:AUTO_INCREMENT PG/金仓:SERIAL / BIGSERIAL 或者 identity(推荐V8新写法)
-- mysql
id bigint primary key auto_increment
-- pg
id bigserial primary key
-- 或者标准identity(推荐)
id bigint primary key generated always as identity
十一、IF表达式
MySQL:IF(条件,val1,val2) PG:CASE WHEN
-- mysql
select IF(sex=1,'男','女') from t;
-- pg
select CASE WHEN sex=1 THEN '男' ELSE '女' END from t;
金仓V8新版本也兼容
IF()函数,但PG标准不推荐,为了稳妥统一用CASE。
十二、LIKE 大小写
MySQL 默认大小写不敏感; PG 默认大小写敏感!
-- pg 不区分大小写like
select * from t where lower(name) like lower('%abc%');
-- 或者使用 ILIKE(PG专属)
select * from t where name ILIKE '%abc%';
十三、REPLACE、TRIM、LENGTH、SUBSTRING
✅ 这些函数基本通用: REPLACE()、TRIM()、LENGTH()、SUBSTRING() 行为基本一致,改动很小。
十四、MyBatis层面额外注意点
- 方言配置:不要用
MySQLDialect,切换为PostgreSQLDialect - 分页插件(PageHelper):方言改成 postgresql
- 主键回填:mysql
useGeneratedKeys写法,PG略有区别,需要指定keyProperty+ 序列
十五、快速自查清单(切换PG模式前跑一遍)
- 全文检索代码有没有
IFNULL、DATE_FORMAT、GROUP_CONCAT、SUBSTRING_INDEX - 有没有
0000-00-00日期 - SQL有没有大量反引号 `````
- 有没有
LIMIT m,n分页写法 - 有没有
||逻辑判断 - MyBatis方言、分页插件配置