Oracle数据库迁移到MySQL数据库
1 字段类型差异
Oracle | MySQL | 解决方案 |
varchar2 | varchar | varchar |
date | date/time/datetime/timestamp | datetime |
clob | tinytext/text/mediumtext/longtext | longtext |
blob | tinyblob/blob/mediumblob/longblob | longblob |
number | tinyint/smallint/mediumint/int/bigint decimal/float/double | Oracle number的取值范围为1-38位 NUMBER(1-2)–TINYINT, NUMBER(3-4)–SMALLINT , NUMBER(5-6)–MEDIUMINT, NUMBER(7-9)–INT, NUMBER(10-19)–BIGINT, NUMBER(20+)或NUMBER(int,int)–DECIMAL 若ORM框架用的Hibernate,建议使用decimal代替number |
2 函数差异(附部分案例)
差异项 | Oracle | MySQL | 案例连接 |
分页 | ROWNUM | limit或自定义变量 | |
空值转换 | NVL(s1,r1):若s1为null,返回r1,否则返回s1; SELECT NVL(NULL, ‘R’) FROM DUAL; SELECT NVL(‘S’, ‘R’) FROM DUAL; Oracle也支持coalesce函数 | ifnull(s1,r1)、coalesce(s1,r1) SELECT coalesce(NULL, ‘R’); SELECT coalesce(‘S’, ‘R’); | |
空值转换2 | NVL2(s1,r1,r2):若s1为null,返回r2,否则返回r1; SELECT NVL2(NULL, ‘R1’, ‘R2’) FROM DUAL; SELECT NVL2(‘S’, ‘R1’, ‘R2’) FROM DUAL; | 可以用case when代替 select case when null is null then ‘R2’ else ‘R1’ end; select case when ‘S’ is null then ‘R2’ else ‘R1’ end; | |
截取 | TRUNC()可以用于数值、日期 | 对于截取日期可以用date_format+str_to_date实现; 对于数字截取可用truncate() | |
序列 | 序列.NEXTVAL | 无序列 | |
系统日期 | SYSDATE | sysdate()、NOW() | |
添加月份 | ADD_MONTHS(date, int) SELECT add_months(to_date(‘2021-05-19’,‘yyyy-MM-dd’), 1) FROM dual; | date_add(date, INTERVAL int month) select date_add(str_to_date(‘2021-05-19’,’%Y-%m-%d’), interval 1 month); | |
两日期间隔的月份 | MONTHS_BETWEEN(date1,date2) | (date1-date2的天数)/31,保留9位小数 | |
类型转换 | TO_DATE() SELECT TO_DATE(‘2021-05-19 17:15:33’,‘yyyy-MM-dd hh24:mi:ss’) FROM DUAL; | str_to_date() select str_to_date(‘2021-05-19 17:15:33’,’%Y-%m-%d %H:%i:%s’); | |
TO_CHAR(date) TO_CHAR(number) | date_format(date) cast(number as char) convert(number,char) | SELECT CONVERT(‘test’, CHAR CHARACTER SET utf8); SELECT CAST(‘test’ AS CHAR CHARACTER SET utf8); | |
字符串截取 | SUBSTR(str,int,int) 第二个参数可正负0 | SUBSTR(str,int,int) 第二个参数可正负,若为0则返回空字符串 | |
INSTR | INSTR(str,subStr,pos)三个参数,可指定开始位置,pos=0返回0,pos<0,从尾面开始查找 | instr(str,subStr)两个参数 locate(subStr,str,pos):pos<=0时返回0 | |
字符串连接 | ||、CONCAT(s1,s2),concat只能有两个参数 | concat(s1,s2,s3,…)可有多个参数 | |
字符串替换 | replace(str, substr) replace(str,substr,repstr) | 仅支持replace(str,substr,repstr) | |
行转列 | WM_CONCAT、LISTAGG | group_concat | |
条件选择 | DECODE | case when | |
正则 | REGEXP_LIKE(expr,pat) | expr REGEXP pat |
3 其他差异
差异项 | Oracle | MySQL |
全局临时表 | 支持 | 不支持 |
表分区 | 支持 | 支持,但有主键是分区字段必须是主键字段 |
FULL JOIN | 支持 | 不支持,left join + right join |
DELETE | 可以没有from关键字 可以用exists | 必须有from 不可以用exists |
正则表达式 | REGEXP_SUBSTR() | REGEXP |
集合相减 | Minus | 无,可用not in |
NULL和’’ | ORACLE认为’‘等同于NULL LENGTH(’’)为NULL TO_DATE(’’,‘YYYYMMDD’)为空 TO_NUMBER(’’,1)为NULL oracle中’’,数值类型的插入,NULL oracle中’’,字符类型,NULL oracle中’’,时间类型,NULL | NULL和’‘不同 LENGTH(’’)为0 TO_DATE(’’,‘YYYYMMDD’),报错 TO_NUMBER(’’,1),报错 MySQL中’’ 数值类型的插入,报错 MySQL中’’ 字符类型,’’ MySQL中’’ 时间类型,报错 |
合并 | MERGE INTO | 无此语法,用存储过程 |
group by having | oracle having语句可以在group by之前 | MySQL having语句必须在group by之后 |
去重 | unique、distinct | distinct |
不等于 | Oracle中 ! =,< >操作符中间允许有空格 | MySQL中不可以,且字符类型与数字类型不可比较 |
别名 | 派生表(即子查询形成的视图)有无别名皆可 ,别名可重复 | MySQL派生表必须有别名 ,别名不可重复,DELETE不能有别名 |
其它 | 支持中文空格,中文逗号 | 不支持 |
数字+and/or 之间可以无空格 | 不支持 |