1.3.3.2.3. 转换为 Oracle19c
1.3.3.2.3.1. 时间日期函数
1.3.3.2.3.1.1. STR_TO_DATE
- 语法
STR_TO_DATE(date,format)- 描述
- 该函数功能是返回日期。
参数解释
参数 |
说明 |
|---|---|
date |
指定日期时间,该参数可以为 text 数据类型 |
format |
日期显示格式,该参数为字符串类型,支持清单详见下表 |
序号 |
日期时间显示格式 |
含义 |
|---|---|---|
1 |
%c |
月,数值(00-12) |
2 |
%d |
月的天,数值(00-31) |
3 |
%e |
月的天,数值(00-31) |
4 |
%H |
小时 (00-23) |
5 |
%h |
小时 (01-12) |
6 |
%I |
小时 (01-12) |
7 |
%i |
分钟,数值(00-59) |
8 |
%k |
小时 (00-23) |
9 |
%l |
小时 (01-12) |
10 |
%M |
月名 |
11 |
%m |
月,数值(00-12) |
12 |
%p |
AM 或 PM |
13 |
%r |
时间,12-小时(hh:mm:ss AM 或 PM) |
14 |
%S |
秒(00-59) |
15 |
%s |
秒(00-59) |
16 |
%T |
时间,24-小时(hh:mm:ss) |
17 |
%W |
星期名 |
18 |
%Y |
年,4位 |
19 |
%y |
年,2位 |
警告
date的范围需要与format范围一致,例如date精确到秒,那么format也需要精确到秒
format的时间格式以转换后Oracle19C的数据库支持为准,’YYYY-MM-MM-DD’与’YYYY-ASD-MM-DD’是不支持的格式
mysql二位数的年份在小于70时是高位补充20,大于70时高位补充19,而oracle二位数的年份高位补充的是20
在源库中,当format中包含日期和时间部分时返回datetime类型,当format中只包含日期部分时返回date类型,当format中只包含时间部分时返回time类型。转换后在目标库中,统一都返回TIMESTAMP类型
示例
-- 转换前MySQL SQL:
SELECT STR_TO_DATE('2024-12-31','%Y-%m-%d %T') FROM DUAL;
+-----------------------------------------+
| STR_TO_DATE('2024-12-31','%Y-%m-%d %T') |
+-----------------------------------------+
| 2024-12-31 00:00:00 |
+-----------------------------------------+
SELECT STR_TO_DATE('70-12-31','%y-%m-%d %T') FROM DUAL;
+---------------------------------------+
| STR_TO_DATE('70-12-31','%y-%m-%d %T') |
+---------------------------------------+
| 1970-12-31 00:00:00 |
+---------------------------------------+
-- 转换后Oracle19C SQL:
SELECT to_date('2024-12-31', 'YY-MM-DD HH24:MI:SS') FROM dual;
TO_DATE('2024-12-31','YY-MM-DDHH24:MI:SS')|
------------------------------------------+
2024-12-31 00:00:00.000|
SELECT to_date('70-12-31', 'YYYY-MM-DD HH24:MI:SS') FROM dual;
TO_DATE('70-12-31','YY-MM-DDHH24:MI:SS')|
----------------------------------------+
2070-12-31 00:00:00.000|
1.3.3.2.3.1.2. NOW
- 语法
NOW()- 描述
- 用于返回当前的日期和时间。
返回类型
DATETIME
警告
统一SQL转换后在目标端数据库执行结果与mysql和mariadb存在一些差异,差异点如下:
mysql和mariadb的now函数受其时区timezone的影响,目标库返回current_timestamp函数,既遵循会话时区,又在结果中包含了时区偏移,两者包含相同的时间和日期信息。
mysql和mariadb的now函数的结果样式固定,目标库返回current_timestamp函数,显示样式受参数NLS_TIMESTAMP_TZ_FORMAT控制.
示例
-- 转换前MySQL SQL:
select now();
now() |
-----------------------+
2025-11-11 10:31:56.000|
-- 转换后Oracle19c SQL:
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF3';
SELECT current_timestamp(0) FROM DUAL;
CURRENT_TIMESTAMP |
-------------------------------------+
2025-11-11 10:31:56.000 +0800 |
1.3.3.2.3.1.3. TIME_FORMAT
- 语法
TIME_FORMAT(date,format)- 描述
- 该函数功能是返回字符串。
参数解释
参数 |
说明 |
|---|---|
time |
指定日期。该参数可以为 timestamp 数据类型 |
format |
日期显示格式,支持清单详见STR_TO_DATE一节 |
警告
format的时间格式不允许出现其它字符。’YYYY-ASD-MM-DD’是不支持的格式
示例
-- 转换前MySQL SQL:
SELECT TIME_FORMAT(SYSDATE(), '%Y-%m-%d %T') FROM dual;
+----------------------------------------+
| TIME_FORMAT(SYSDATE() , '%Y-%m-%d %T') |
+----------------------------------------+
| 0000-00-00 13:14:09 |
+----------------------------------------+
-- 转换后Oracle19C SQL:
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM dual;
TO_CHAR(SYSDATE,'YYYY-MM-DDHH24:MI:SS')|
---------------------------------------+
2025-03-28 15:07:40 |
1.3.3.2.3.1.4. TIMESTAMPDIFF
- 语法
TIMESTAMPDIFF(unit, date1, date2)- 描述
- 返回两个日期/时间之间的差值,根据 unit 单位进行计算,结果为整数
参数解释
参数 |
说明 |
|---|---|
unit |
时间单位,支持 SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、YEAR。大小写不敏感。 |
date1 |
支持DATE、DATETIME、TIMESTAMP数据类型的日期时间表达式,字符串范围为年月日、年月日 时分秒;日期分隔符(-、/、.),时间分隔符(:、.)不可混用每次只能用一种,不支持中文和时区,表示减数。 |
date2 |
支持DATE、DATETIME、TIMESTAMP数据类型的日期时间表达式,字符串范围为年月日、年月日 时分秒;日期分隔符(-、/、.),时间分隔符(:、.)不可混用每次只能用一种,不支持中文和时区,表示被减数。 |
返回类型
INT
警告
由于源库MySQL和目标库数据库历法的不同,MySQL因为1582年格里高利历改革导致的日期跳跃,目标库不跳跃,所以参数为1582-10-15之前的日期结果有差异;
不支持时区相关的参数。
示例
-- 转换前MySQL SQL:
SELECT
TIMESTAMPDIFF(SECOND, STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '2021-01-02 10:13:13.123') AS diff_second,
TIMESTAMPDIFF(MINUTE, STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '2022-03-02 10:13:13') AS diff_minute,
TIMESTAMPDIFF(HOUR, STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '2023-04-02 10:13:13') AS diff_hour,
TIMESTAMPDIFF(DAY, STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '2024-05-02 10:13:13') AS diff_day
diff_second|diff_minute|diff_hour|diff_day|
-----------+-----------+---------+--------+
31716000| 1139160| 28490| 1583|
select
TIMESTAMPDIFF(WEEK, STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '2025-06-15 10:13:13') AS diff_week,
TIMESTAMPDIFF(MONTH, STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '2026-07-01 10:13:13') AS diff_month,
TIMESTAMPDIFF(YEAR, STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '2027-08-01 10:13:13') AS diff_year;
diff_week|diff_month|diff_year|
---------+----------+---------+
284| 78| 7|
-- 转换后Oracle19C SQL:
SELECT unisql.convert.timestampdiff('second', to_date('2020-01-01 08:13:13', 'YYYY-MM-DD HH24:MI:SS'), '2021-01-02 10:13:13.123') AS diff_second,unisql.convert.timestampdiff('minute', to_date('2020-01-01 08:13:13', 'YYYY-MM-DD HH24:MI:SS'), '2022-03-02 10:13:13') AS diff_minute,unisql.convert.timestampdiff('hour', to_date('2020-01-01 08:13:13', 'YYYY-MM-DD HH24:MI:SS'), '2023-04-02 10:13:13') AS diff_hour,unisql.convert.timestampdiff('day', to_date('2020-01-01 08:13:13', 'YYYY-MM-DD HH24:MI:SS'), '2024-05-02 10:13:13') AS diff_day FROM DUAL
DIFF_SECOND|DIFF_MINUTE|DIFF_HOUR|DIFF_DAY|
-----------+-----------+---------+--------+
31716000| 1139160| 28490| 1583|
SELECT unisql.convert.timestampdiff('week', to_date('2020-01-01 08:13:13', 'YYYY-MM-DD HH24:MI:SS'), '2025-06-15 10:13:13') AS diff_week,unisql.convert.timestampdiff('month', to_date('2020-01-01 08:13:13', 'YYYY-MM-DD HH24:MI:SS'), '2026-07-01 10:13:13') AS diff_month,unisql.convert.timestampdiff('year', to_date('2020-01-01 08:13:13', 'YYYY-MM-DD HH24:MI:SS'), '2027-08-01 10:13:13') AS diff_year FROM DUAL
DIFF_WEEK|DIFF_MONTH|DIFF_YEAR|
---------+----------+---------+
284| 78| 7|
1.3.3.2.3.1.5. DATEDIFF
- 语法
DATEDIFF(date1, date2)- 描述
- 用于计算两个日期之间相差的天数(date1 - date2),返回结果为整数。
参数解释
参数 |
说明 |
|---|---|
date1 |
支持DATE、DATETIME、TIMESTAMP数据类型的日期时间表达式,字符串范围为年月日、年月日 时分秒;日期分隔符(-、/、.),时间分隔符(:、.)不可混用每次只能用一种,不支持中文和时区,表示被减数。 |
date2 |
支持DATE、DATETIME、TIMESTAMP数据类型的日期时间表达式,字符串范围为年月日、年月日 时分秒;日期分隔符(-、/、.),时间分隔符(:、.)不可混用每次只能用一种,不支持中文和时区,表示减数。 |
返回类型
INT
警告
由于源库MySQL和目标库数据库历法的不同,MySQL因为1582年格里高利历改革导致的日期跳跃,目标库不跳跃,所以参数为1582-10-15之前的日期结果有差异;
不支持时区相关的参数。
示例
-- 转换前MySQL SQL:
select datediff(STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '2025-11-11 23:13:13');
datediff(STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '2025-11-11 23:13:13')|
---------------------------------------------------------------------------------------+
-2141|
-- 转换后Oracle19C SQL:
SELECT unisql.convert.datediff(to_date('2020-01-01 08:13:13', 'YYYY-MM-DD HH24:MI:SS'), '2025-11-11 23:13:13') FROM DUAL
UNISQL.CONVERT.DATEDIFF(TO_DATE('2020-01-0108:13:13','YYYY-MM-DDHH24:MI:SS'),'2025-11-1123:13:13')|
--------------------------------------------------------------------------------------------------+
-2141|
1.3.3.2.3.1.6. DATE_FORMAT
- 语法
DATE_FORMAT(date,format)- 描述
- 用于将日期/时间格式化为字符串的函数
参数解释
参数 |
说明 |
|---|---|
date |
支持DATE、DATETIME、TIMESTAMP数据类型的日期时间表达式,字符串范围为年月日、年月日 时分秒;日期分隔符(-、/、.),时间分隔符(:、.)不可混用每次只能用一种,不支持中文和时区; |
format |
格式化字符串,只支持常量字符串,支持的格式转化见下表 |
原格式 |
目标格式 |
说明 |
|---|---|---|
%c |
MM |
月份,数值 |
%d |
DD |
日,数值(00-31) |
%e |
DD |
日,数值(0-31) |
%f |
FF6 |
微秒 |
%H |
HH24 |
小时 (00-23) |
%h |
HH12 |
小时 (01-12) |
%I |
HH12 |
小时 (01-12) |
%i |
MI |
分钟,数值(00-59) |
%k |
HH24 |
小时 (0-23) |
%l |
HH12 |
小时 (1-12) |
%M |
Month |
月份名 |
%m |
MM |
月,数值(00-12) |
%S |
SS |
秒(00-59) |
%s |
SS |
秒(00-59) |
%T |
HH24:MI:SS |
时间, 24-小时 (hh:mm:ss) |
%Y |
YYYY |
年,4 位 |
%y |
YY |
年,2 位 |
%W |
Day |
星期名(如 Monday) |
%p |
AM |
上午/下午(AM 或 PM) |
%r |
HH:MI:SS AM |
12 小时制时间(含 AM/PM) |
返回类型
VARCHAR
警告
统一SQL转换后在目标端数据库执行结果与mysql和mariadb存在一些差异,差异点如下:
mysql和mariadb的日期格式部分日期格式,如%c、%e、%k、%l,不会补前导零,目标库返回对应的日期格式会有前导零。
mysql和mariadb的date数据类型支持%f的日期格式,目标库的date类型不支持转化的FF6日期格式。
mysql和mariadb的日期格式%W(星期名)返回都是英文,目标库通过设置 NLS_DATE_LANGUAGE 来设定返回对应的语言。
字符串日期格式非法mysql返回的是null,目标库则会报错;
日期时间需要为标准格式,年4位,月、日、时、分、秒2位
date、timestamp和timestamptz目标库返回显示样式受参数NLS_DATE_FORMAT、NLS_TIMESTAMP_FORMAT、NLS_TIMESTAMP_TZ_FORMAT控制
示例
-- 转换前MySQL SQL:
select date_format(STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '%Y/%m/%d %h %i %s');
date_format(STR_TO_DATE('2020-01-01 08:13:13','%Y-%m-%d %H:%i:%s'), '%Y/%m/%d %h %i %s')|
----------------------------------------------------------------------------------------+
2020/01/01 08 13 13 |
-- 转换后Oracle19C SQL:
SELECT to_char(unisql.convert.str_to_timestamp(to_date('2020-01-01 08:13:13', 'YYYY-MM-DD HH24:MI:SS')), 'YYYY/MM/DD HH MI SS') FROM DUAL
TO_CHAR(UNISQL.CONVERT.STR_TO_TIMESTAMP(TO_DATE('2020-01-0108:13:13','YYYY-MM-DDHH24:MI:SS')),'YYYY/MM/DDHHMISS')|
-----------------------------------------------------------------------------------------------------------------+
2020/01/01 08 13 13 |
1.3.3.2.3.1.7. DATE_ADD
- 语法
DATE_ADD (date, INTERVAL expr unit)- 描述
- 用于将指定的时间间隔添加到日期时间值上并返回。
参数解释
参数 |
说明 |
|---|---|
date |
日期时间,该参数可以为date、datetime、timestamp数据类型或者int、number、字符串。 范围为年月日、年月日 时分秒;日期分隔符(-、/、.),时间分隔符(:、.)不可混用每次只能用一种; |
expr |
时间间隔,暂不支持小数 |
unit |
时间单位,支持清单:年(year)/月(month)/日(day)/时(hour)/分(minute)/秒(second) |
警告
统一 SQL 转换后需使用自定义函数
unisql.convert.date_add(date, expr, unit),见下方sql示例。参数
expr暂不支持小数,且转换前后结果可能存在差异:
原sql
SELECT DATE_ADD('2024-02-29', INTERVAL 1.1 year);返回2025-02-28;转换后
SELECT unisql.convert.date_add('2024-02-29', to_number(1.1), 'year') FROM DUAL返回2025-03-29。
参数
expr转换后在oracle_19c执行使用to_number函数包裹,to_number限制如下:不支持非数字字符,sql示例如下,SELECT TO_NUMBER(‘123abc’) AS 含字母数字 FROM DUAL;
SELECT TO_NUMBER(‘45-67’) AS 中间带横杠 FROM DUAL;
SELECT TO_NUMBER(‘78#90’) AS 含特殊字符 FROM DUAL;
不支持多个小数点,sql示例,SELECT TO_NUMBER(‘12.34.56’) AS 多个小数点 FROM DUAL;
参数
date的格式需严格遵循年月日时分秒的顺序。参数
date支持的函数(以源库mysql为基准)包括:NOW()、SYSDATE()、TIMESTAMP()、CURDATE()、CURRENT_TIME()、FROM_UNIXTIME()、STR_TO_DATE()、DATE_FORMAT(),其对应的格式也需按年月日时分秒顺序设置。
额外支持时间单位 week ,示例sql如下,在oracle19c执行下面sql
-- 下方补丁函数既包括date_sub也包括date_add,当前本地日期时间是2025-11-12 20:04:57.440285000 SELECT -- TIMESTAMP 类型 + 带空格单位 unisql.convert.date_add(SYSTIMESTAMP, to_number(1), ' WEEK ') AS ts_add_1week, -- DATE 类型 - WEEK unisql.convert.date_sub(SYSDATE, to_number(1), 'week') AS date_sub_1week, -- TIMESTAMP WITH TIME ZONE 类型(UTC 偏移量)+ 2 周 unisql.convert.date_add(SYSTIMESTAMP AT TIME ZONE 'UTC', to_number(2), 'WEEK') AS tztz_add_2week, -- TIMESTAMP WITH TIME ZONE 类型(区域名称)+ 3 周 unisql.convert.date_add(SYSTIMESTAMP AT TIME ZONE 'Asia/Shanghai', to_number(3), 'WEEK') AS tztz_region_add_3week FROM DUAL;
上面sql执行结果格式化后如下图:
字段名 |
格式化后结果(标准格式) |
数据类型 |
计算逻辑 |
关键说明(验证修复效果) |
ts_add_1week |
2025-11-19 20:04:57.440285000 +08:00 |
TIMESTAMP WITH TIME ZONE |
当前本地时间(+08:00) + 1周(7天) |
✅ 带空格单位’ WEEK ‘被TRIM处理;✅ 日期12+7=19;✅ 保留时分秒+时区 |
date_sub_1week |
2025-11-05 |
DATE |
当前本地日期 - 1周(7天) |
✅ 小写’week’被UPPER兼容;✅ DATE仅保留年月日;✅ 日期12-7=5 |
tztz_add_2week |
2025-11-26 12:04:57.440285000 UTC(+00:00) |
TIMESTAMP WITH TIME ZONE |
UTC时区时间 + 2周(14天) |
✅ 兼容UTC偏移量;❌ 无ORA-01882;✅ 日期12+14=26 |
tztz_region_add_3week |
2025-12-03 20:04:57.440285000 ASIA/SHANGHAI(+08:00) |
TIMESTAMP WITH TIME ZONE |
亚洲/上海时区时间 + 3周(21天) |
✅ 兼容Asia/Shanghai;✅ 跨月11-12→12-03;✅ 保留时区 |
示例
-- 转换前MySQL SQL:
SELECT DATE_ADD('2024-02-29', INTERVAL 1 year);
+-----------------------------------------+
| DATE_ADD('2024-02-29', INTERVAL 1 year) |
+-----------------------------------------+
| 2025-02-28 |
+-----------------------------------------+
SELECT DATE_ADD(null, INTERVAL 1 DAY);
+--------------------------------+
| DATE_ADD(null, INTERVAL 1 DAY) |
+--------------------------------+
| NULL |
+--------------------------------+
SELECT DATE_ADD(?, INTERVAL 1 DAY);
SELECT DATE_ADD('2025-12-31', INTERVAL 1 DAY);
+----------------------------------------+
| DATE_ADD('2025-12-31', INTERVAL 1 DAY) |
+----------------------------------------+
| 2026-01-01 |
+----------------------------------------+
-- 转换后Oracle SQL:
SELECT unisql.convert.date_add('2024-02-29', to_number(1), 'year') FROM DUAL;
UNISQL.CONVERT.DATE_ADD('2024-02-29',TO_NUMBER(1),'YEAR')
---------------------------------------------------------------------------
28-FEB-25 12.00.00.000000000 AM
SELECT unisql.convert.date_add('', to_number(1), 'day') FROM DUAL;
UNISQL.CONVERT.DATE_ADD('',TO_NUMBER(1),'DAY')
---------------------------------------------------------------------------
SELECT unisql.convert.date_add(?, to_number(1), 'day') FROM DUAL
SELECT unisql.convert.date_add('2025-12-31', to_number(1), 'day') FROM DUAL;
UNISQL.CONVERT.DATE_ADD('2025-12-31',TO_NUMBER(1),'DAY')
---------------------------------------------------------------------------
01-JAN-26 12.00.00.000000000 AM
1.3.3.2.3.1.8. DATE_SUB
- 语法
DATE_SUB (date, INTERVAL expr unit)- 描述
- 用于日期时间减去时间间隔并返回。
参数解释
参数 |
说明 |
|---|---|
date |
日期时间,该参数可以为date、datetime、timestamp数据类型或者int、number、字符串。 范围为年月日、年月日 时分秒;日期分隔符(-、/、.),时间分隔符(:、.)不可混用每次只能用一种; |
expr |
时间间隔,暂不支持小数 |
unit |
时间单位,支持清单:年(year)/月(month)/日(day)/时(hour)/分(minute)/秒(second) |
警告
统一 SQL 转换后需使用自定义函数
unisql.convert.date_sub(date, expr, unit),见下方sql示例。参数
expr暂不支持小数,且转换前后结果可能存在差异:
原sql
SELECT DATE_SUB('2024-02-29', INTERVAL 1.1 year);返回2023-02-28;转换后
SELECT unisql.convert.date_sub('2024-02-29', to_number(1.1), 'year') FROM DUAL返回2023-01-29。
参数
expr转换后在oracle_19c执行使用to_number函数包裹,to_number限制如下:不支持非数字字符,sql示例如下,SELECT TO_NUMBER(‘123abc’) AS 含字母数字 FROM DUAL;
SELECT TO_NUMBER(‘45-67’) AS 中间带横杠 FROM DUAL;
SELECT TO_NUMBER(‘78#90’) AS 含特殊字符 FROM DUAL;
不支持多个小数点,sql示例,SELECT TO_NUMBER(‘12.34.56’) AS 多个小数点 FROM DUAL;
参数
date的格式需严格遵循年月日时分秒的顺序。参数
date支持的函数(以源库mysql为基准)包括:NOW()、SYSDATE()、TIMESTAMP()、CURDATE()、CURRENT_TIME()、FROM_UNIXTIME()、STR_TO_DATE()、DATE_FORMAT(),其对应的格式也需按年月日时分秒顺序设置。
额外支持时间单位 week ,示例sql如下,在oracle19c执行下面sql
-- 下方补丁函数既包括date_sub也包括date_add,当前本地日期时间是2025-11-12 20:04:57.440285000 SELECT -- TIMESTAMP 类型 + 带空格单位 unisql.convert.date_add(SYSTIMESTAMP, to_number(1), ' WEEK ') AS ts_add_1week, -- DATE 类型 - WEEK unisql.convert.date_sub(SYSDATE, to_number(1), 'week') AS date_sub_1week, -- TIMESTAMP WITH TIME ZONE 类型(UTC 偏移量)+ 2 周 unisql.convert.date_add(SYSTIMESTAMP AT TIME ZONE 'UTC', to_number(2), 'WEEK') AS tztz_add_2week, -- TIMESTAMP WITH TIME ZONE 类型(区域名称)+ 3 周 unisql.convert.date_add(SYSTIMESTAMP AT TIME ZONE 'Asia/Shanghai', to_number(3), 'WEEK') AS tztz_region_add_3week FROM DUAL;
上面sql执行结果格式化后如下图:
字段名 |
格式化后结果(标准格式) |
数据类型 |
计算逻辑 |
关键说明(验证修复效果) |
ts_add_1week |
2025-11-19 20:04:57.440285000 +08:00 |
TIMESTAMP WITH TIME ZONE |
当前本地时间(+08:00) + 1周(7天) |
✅ 带空格单位’ WEEK ‘被TRIM处理;✅ 日期12+7=19;✅ 保留时分秒+时区 |
date_sub_1week |
2025-11-05 |
DATE |
当前本地日期 - 1周(7天) |
✅ 小写’week’被UPPER兼容;✅ DATE仅保留年月日;✅ 日期12-7=5 |
tztz_add_2week |
2025-11-26 12:04:57.440285000 UTC(+00:00) |
TIMESTAMP WITH TIME ZONE |
UTC时区时间 + 2周(14天) |
✅ 兼容UTC偏移量;❌ 无ORA-01882;✅ 日期12+14=26 |
tztz_region_add_3week |
2025-12-03 20:04:57.440285000 ASIA/SHANGHAI(+08:00) |
TIMESTAMP WITH TIME ZONE |
亚洲/上海时区时间 + 3周(21天) |
✅ 兼容Asia/Shanghai;✅ 跨月11-12→12-03;✅ 保留时区 |
示例
-- 转换前MySQL SQL:
SELECT DATE_SUB('2024-02-29', INTERVAL 1 year);
+-----------------------------------------+
| DATE_SUB('2024-02-29', INTERVAL 1 year) |
+-----------------------------------------+
| 2023-02-28 |
+-----------------------------------------+
SELECT DATE_SUB(null, INTERVAL 1 DAY);
+--------------------------------+
| DATE_SUB(null, INTERVAL 1 DAY) |
+--------------------------------+
| NULL |
+--------------------------------+
SELECT DATE_SUB(?, INTERVAL 1 DAY);
SELECT DATE_SUB('2025-12-31', INTERVAL 1 DAY);
+----------------------------------------+
| DATE_SUB('2025-12-31', INTERVAL 1 DAY) |
+----------------------------------------+
| 2025-12-30 |
+----------------------------------------+
-- 转换后Oracle SQL:
SELECT unisql.convert.date_sub('2024-02-29', to_number(1), 'year') FROM DUAL;
UNISQL.CONVERT.DATE_SUB('2024-02-29',TO_NUMBER(1),'YEAR')
---------------------------------------------------------------------------
28-FEB-23 12.00.00.000000000 AM
SELECT unisql.convert.date_sub('', to_number(1), 'day') FROM DUAL;
UNISQL.CONVERT.DATE_SUB('',TO_NUMBER(1),'DAY')
---------------------------------------------------------------------------
SELECT unisql.convert.date_sub(?, to_number(1), 'day') FROM DUAL;
SELECT unisql.convert.date_sub('2025-12-31', to_number(1), 'day') FROM DUAL;
UNISQL.CONVERT.DATE_SUB('2025-12-31',TO_NUMBER(1),'DAY')
---------------------------------------------------------------------------
30-DEC-25 12.00.00.000000000 AM
1.3.3.2.3.1.9. ADDDATE
- 语法
ADDDATE (date, INTERVAL expr unit)ADDDATE (date, days)- 描述
- 用于将指定的时间间隔添加到日期时间上并返回。
参数解释
参数 |
说明 |
|---|---|
date |
日期时间,该参数可以为date、datetime、timestamp数据类型或者int、number、字符串。 范围为年月日、年月日 时分秒;日期分隔符(-、/、.),时间分隔符(:、.)不可混用每次只能用一种; |
expr |
时间间隔,暂不支持小数 |
unit |
时间单位,支持清单:年(year)/月(month)/日(day)/时(hour)/分(minute)/秒(second) |
警告
mysql的函数ADDDATE(date, days)等价于ADDDATE(date, INTERVAL days DAY),mysql中ADDDATE函数语义与Date_add函数相同。DATE_ADD
统一 SQL 转换后需使用自定义函数
unisql.convert.date_add(date, interval, unit)示例如下:
原 SQL:
SELECT ADDDATE('2025-10-09 23:00:00', INTERVAL 1 hour),返回2025-10-10 00:00:00转换后:
SELECT unisql.convert.date_add('2025-10-09 23:00:00', to_number(1), 'hour') FROM DUAL, 返回2025-10-10 00:00:00
参数
expr暂不支持小数,且转换前后结果可能存在差异:原 SQL
SELECT ADDDATE('2024-02-29', INTERVAL 1.1 year);返回2025-02-28;转换后
SELECT unisql.convert.date_add('2024-02-29', to_number(1.1), 'year') FROM DUAL返回2025-03-29。
参数
expr转换后在oracle_19c执行使用to_number函数包裹,to_number限制如下:不支持非数字字符,sql示例,SELECT TO_NUMBER(‘123abc’) AS 含字母数字 FROM DUAL;,SELECT TO_NUMBER(‘45-67’) AS 中间带横杠 FROM DUAL;,SELECT TO_NUMBER(‘78#90’) AS 含特殊字符 FROM DUAL;不支持多个小数点,sql示例,SELECT TO_NUMBER(‘12.34.56’) AS 多个小数点 FROM DUAL;
参数
date的格式需严格遵循年月日时分秒的顺序。也支持week,参考date_add函数部分 DATE_ADD支持作为
date入参的函数(以mysql为基准)包括:NOW()、SYSDATE()、TIMESTAMP()、CURDATE()、CURRENT_TIME()、FROM_UNIXTIME()、STR_TO_DATE()、DATE_FORMAT(),其对应的格式也需按年月日时分秒顺序设置。
示例
-- 转换前MySQL SQL:
SELECT ADDDATE('2023-10-01', INTERVAL 3 DAY);
+---------------------------------------+
| ADDDATE('2023-10-01', INTERVAL 3 DAY) |
+---------------------------------------+
| 2023-10-04 |
+---------------------------------------+
SELECT ADDDATE('2023-10-01', 3 );
+---------------------------+
| ADDDATE('2023-10-01', 3 ) |
+---------------------------+
| 2023-10-04 |
+---------------------------+
SELECT ADDDATE(null, INTERVAL 1 WEEK);
+--------------------------------+
| ADDDATE(null, INTERVAL 1 WEEK) |
+--------------------------------+
| NULL |
+--------------------------------+
SELECT ADDDATE(?, INTERVAL 1 WEEK);
-- 转换后Oracle SQL:
SELECT unisql.convert.date_add('2023-10-01', to_number(3), 'day') FROM DUAL;
UNISQL.CONVERT.DATE_ADD('2023-10-01',TO_NUMBER(3),'DAY')
---------------------------------------------------------------------------
04-OCT-23 12.00.00.000000000 AM
SELECT unisql.convert.date_add('2023-10-01', to_number(3), 'day') FROM DUAL;
UNISQL.CONVERT.DATE_ADD('2023-10-01',TO_NUMBER(3),'DAY')
---------------------------------------------------------------------------
04-OCT-23 12.00.00.000000000 AM
SELECT unisql.convert.date_add('', to_number(1), 'week') FROM DUAL;
UNISQL.CONVERT.DATE_ADD('',TO_NUMBER(1),'WEEK')
---------------------------------------------------------------------------
SELECT unisql.convert.date_add(?, to_number(1), 'week') FROM DUAL
1.3.3.2.3.2. 条件函数
1.3.3.2.3.2.1. IF
- 语法
IF (expr1, expr2, expr3)- 描述
- 如果第一个参数为TRUE,则返回第二个参数,否则返回第三个参数。
参数解释
参数 |
说明 |
|---|---|
expr1 |
判断该参数是否为true |
expr2 |
如果expr1为true,则返回expr2 |
expr3 |
如果expr1不为true,则返回expr3 |
警告
MySQL 中,null和空字符串不相等,而 Oracle 19c 中,null和空字符串相等都是null。
Oracle 19c 中null相关表达式操作会返回null
expr1中null相关表达式操作会返回null
Oracle 19c 类型转换规则方面与 MySQL 不同,expr2 与 expr3 必须是相同的类型,否则会报错
ORA-00932: 数据类型不一致; 如select if (1 > 2, 1, '假')是不支持的当参数expr1非表达式时,会调用函数is_nonzero判断是否为真。
is_nonzero的入参是VARCHAR2,因此如果参数expr1隐式转换为字符串时,mysql和oceanbase-oracle存在差异,如日期类型转字符串,会受到日期格式的影响。 参数expr1如果是数值类型的字符串会转为数值和0比较,非0则返回TRUE。 参数expr1如果是非数值类型的字符串则返回FALSE。 以数值开头的非数值类型字符串如1abc,Mysql会进行截取为数值1和0比较,暂不支持,Oracle 19c将返回FALSE。
示例
-- 转换前MySQL SQL:
SELECT IF(1 > 2, 2, 3);
IF(1 > 2, 2, 3)|
---------------+
3|
SELECT IF(1, 2, 3);
IF(1, 2, 3)|
-----------+
2|
SELECT IF('123', 2, 3);
IF('123', 2, 3)|
---------------+
2|
-- 转换后 Oracle 19c SQL:
SELECT case when 1>2 then 2 else 3 end from dual;
CASEWHEN1>2THEN2ELSE3END|
--+
3|
SELECT case when unisql.is_nonzero(1) != 0 then 2 else 3 end from dual;
CASEWHENUNISQL.IS_NONZERO(1)!=0THEN2ELSE3END|
--+
2|
SELECT case when unisql.is_nonzero('123') != 0 then 2 else 3 end from dual;
CASEWHENUNISQL.IS_NONZERO('123')!=0THEN2ELSE3END|
--+
2|
1.3.3.2.3.2.2. IFNULL
- 语法
IFNULL (anycompatible1, anycompatible2)- 描述
- 根据参数是否为空,返回相应的值。
参数解释
参数 |
说明 |
|---|---|
anycompatible1 |
判断该参数是否为null,如果不为null,则返回该参数 |
anycompatible2 |
判断第一个参数是否为null,如果为null,则返回该参数 |
警告
由于Oracle19C中无法区分空串与NULL,所以在Oracle19C中,只能将’’与NULL一视同仁来处理
示例
-- 转换前MySQL SQL:
SELECT ifnull(1, 15) FROM dual;
+---------------+
| ifnull(1, 15) |
+---------------+
| 1 |
+---------------+
select ifnull(null, 15) FROM dual;
+------------------+
| ifnull(null, 15) |
+------------------+
| 15 |
+------------------+
select ifnull('', 15) FROM dual;
+----------------+
| ifnull('', 15) |
+----------------+
| |
+----------------+
-- 转换后Oracle19C SQL:
SELECT nvl(1, 15) FROM dual;
NVL(1,15)|
---------+
1|
SELECT nvl(NULL, 15) FROM dual;
NVL(NULL,15)|
------------+
15|
SELECT nvl('', 15) FROM dual;
NVL('',15)|
----------+
15 |
1.3.3.2.3.2.3. ISNULL
- 语法
ISNULL (anycompatible)- 描述
- 判断是否为null,为null则返回1,非null返回0
参数解释
参数 |
说明 |
|---|---|
anycompatible |
判断该参数是否为null |
警告
由于Oracle19C中无法区分空串与NULL,所以在Oracle19C中,只能将’’与NULL一视同仁来处理
示例
create table t1(id text);
insert into t1 values(123), (null), ('a');
-- 转换前MySQL SQL:
select isnull(1) FROM dual;
+-----------+
| isnull(1) |
+-----------+
| 0 |
+-----------+
select isnull(null) FROM dual;
+--------------+
| isnull(null) |
+--------------+
| 1 |
+--------------+
select isnull('') FROM dual;
+------------+
| isnull('') |
+------------+
| 0 |
+------------+
-- 转换后Oracle19C SQL:
SELECT CASE WHEN 1 IS NULL THEN 1 ELSE 0 END FROM dual;
CASEWHEN1ISNULLTHEN1ELSE0END|
----------------------------+
0|
SELECT CASE WHEN null IS NULL THEN 1 ELSE 0 END FROM dual;
CASEWHENNULLISNULLTHEN1ELSE0END|
-------------------------------+
1|
SELECT CASE WHEN '' IS NULL THEN 1 ELSE 0 END FROM dual;
CASEWHEN''ISNULLTHEN1ELSE0END|
-----------------------------+
1|
1.3.3.2.3.3. 字符串函数
1.3.3.2.3.3.1. FIND_IN_SET
- 语法
FIND_IN_SET (str, strlist)- 描述
- 返回一个字符串 str 在另一个由逗号隔开的字符串 strlist 中第一次出现的位置。
参数解释
参数 |
说明 |
|---|---|
str |
需要查找的字符串,不能包含逗号,包含逗号则该函数无法正常工作 |
strlist |
字符串清单,是一个以逗号分隔的字符串 |
警告
MySQL 中,null和空字符串不相等,而oracle19c中,null和空字符串相等都是null;所以无法实现在 strlist 中寻找空串的功能。
只要 str 或 strlist 为 null 或空串,函数就会返回 NULL
大小写处理方面,MySQL 是根据数据库或列的字符集来决定是否区分大小写的;而 Oracle 19c 中,本函数 区分大小写
入参仅支持字符串类型,以及可以隐式转换成字符串的类型如 NUMBER
如果您的表中含义一个定长的
CHAR(n)列,且内容未达到 n 长度,则最后一项的匹配会有差异!比如FIND_IN_SET('5', char_col),char_col 为 ‘1,2,3,4,5’ ,但 char_col 类型的长度超过 9,则在 MySQL 中可以匹配返回 5 , 但在 Oracle 中会返回 0 ,因为字符串会视为 ‘1,2,3,4,5 ‘ (带有空格补全)
示例
-- 转换前MySQL SQL:
SELECT FIND_IN_SET('橙子', '苹果,香蕉,橙子') from dual;
FIND_IN_SET('橙子', '苹果,香蕉,橙子')|
-----------------------------+
3|
SELECT FIND_IN_SET(' apple ', ' apple , banana , orange ') from dual;
FIND_IN_SET(' apple ', ' apple , banana , orange ')|
-----------------------------------------------------------+
1|
-- 转换后 Oracle 19c SQL:
SELECT FIND_IN_SET('橙子', '苹果,香蕉,橙子') from dual;
UNISQL.FIND_IN_SET('橙子','苹果,香蕉,橙子')|
-----------------------------------+
3|
SELECT FIND_IN_SET(' apple ', ' apple , banana , orange ') from dual;
UNISQL.FIND_IN_SET('APPLE','APPLE,BANANA,ORANGE')|
-------------------------------------------------+
1|
1.3.3.2.3.3.2. SUBSTRING_INDEX
- 语法
SUBSTRING_INDEX (str, delimiter, count)- 描述
- 根据指定的分隔符 delimiter 和计数 count,从字符串 str 中提取子字符串。 若 count 为正数,则返回从字符串开头到第 count 个分隔符的所有内容; 若 count 为负数,则返回从字符串末尾到第 count 个分隔符的所有内容。
参数解释
参数 |
说明 |
|---|---|
str |
要处理的原始字符串 |
delimiter |
用于分割字符串的分隔符,必须为字符串类型 |
count |
整数,指定分隔符的计数。正数表示从开头计数,负数表示从末尾计数 |
警告
MySQL 中,null和空字符串不相等,而oracle19c中,null和空字符串相等,都为null;若 str、delimiter 或 count 为 null,则函数会返回 NULL。
本函数 区分大小写
入参仅支持字符串类型,以及可以隐式转换成字符串的类型如 NUMBER
如果您的表中含有一个定长的
CHAR(n)列,且内容未达到 n 长度,则最后一项的匹配会有差异。 比如 SUBSTRING_INDEX(char_col, ‘,’, 2) ,char_col 为 ‘1,2,3’ ,但 char_col 类型的长度超过 5,则在 MySQL 中可以正常提取子字符串, 而在 Oracle 中由于字符串会视为 ‘1,2,3 ‘ (带有空格补全),可能会出现提取结果不一致的情况
示例
-- 转换前MySQL SQL:
SELECT SUBSTRING_INDEX('www.example.com', '.', 2) from dual;
SUBSTRING_INDEX('www.example.com', '.', 2)|
-----------------------------------------+
www.example|
SELECT SUBSTRING_INDEX('www.example.com', '.', -2) from dual;
SUBSTRING_INDEX('www.example.com', '.', -2)|
------------------------------------------+
example.com|
-- 转换后 Oracle 19c SQL:
SELECT UNISQL.SUBSTRING_INDEX('www.example.com', '.', 2) from dual;
UNISQL.SUBSTRING_INDEX('www.example.com', '.', 2)|
-----------------------------------------------+
www.example|
SELECT UNISQL.SUBSTRING_INDEX('www.example.com', '.', -2) from dual;
UNISQL.SUBSTRING_INDEX('www.example.com', '.', -2)|
-----------------------------------------------+
example.com|
1.3.3.2.3.3.3. LOCATE
- 语法
LOCATE (substr, str [, position])- 描述
- 返回子字符串第一次出现的位置。
参数解释
参数 |
说明 |
|---|---|
substr |
需要查找的字串,该参数为字符串类型 |
str |
需要被查找的父串,该参数为字符串类型 |
position |
从父串中指定位置开始查找子串(初始值为1),该参数为整形类型,可选参数,不填时默认从父串启示位置开始查找子串 |
警告
由于Oracle19C中无法区分空串与NULL,所以在Oracle19C中只能将’’与NULL一视同仁来处理
Mysql根据排序规则可以设置区分大小写,而oracle不行,所以转换后的函数大小写敏感
示例
-- 转换前MySQL SQL:
SELECT LOCATE('bar', 'foobarbar', 5) FROM dual;
+-------------------------------+
| LOCATE('bar', 'foobarbar', 5) |
+-------------------------------+
| 7 |
+-------------------------------+
SELECT LOCATE('bar', 'foobarbar', 1) FROM dual;
+-------------------------------+
| LOCATE('Bar', 'foobarbar', 1) |
+-------------------------------+
| 4 |
+-------------------------------+
SELECT LOCATE('Bar', 'foobarbar', 1) FROM dual;
+-------------------------------+
| LOCATE('Bar', 'foobarbar', 1) |
+-------------------------------+
| 4 |
+-------------------------------+
SELECT LOCATE('', 'foobarbar', 1) FROM dual;
+----------------------------+
| LOCATE('', 'foobarbar', 1) |
+----------------------------+
| 1 |
+----------------------------+
SELECT LOCATE(NULL, 'foobarbar', 1) FROM dual;
+------------------------------+
| LOCATE(NULL, 'foobarbar', 1) |
+------------------------------+
| NULL |
+------------------------------+
-- 转换后Oracle19C SQL:
SELECT instr('foobarbar', 'bar', 5) FROM dual;
INSTR('FOOBARBAR','BAR',5)|
--------------------------+
7|
SELECT instr('foobarbar', 'bar', 1) FROM dual;
INSTR('FOOBARBAR','BAR',1)|
--------------------------+
4|
SELECT instr('foobarbar', 'Bar', 1) FROM dual;
INSTR('FOOBARBAR','BAR',1)|
--------------------------+
0|
SELECT instr('foobarbar', NULL, 1) FROM dual;
INSTR('FOOBARBAR',NULL,1)|
-------------------------+
|
SELECT instr('foobarbar', '', 1) FROM dual;
INSTR('FOOBARBAR','',1)|
-----------------------+
|
1.3.3.2.3.3.4. CAST
- 语法
CAST (expr AS type)- 描述
- 将expr转换为指定的数据类型。
参数解释
参数 |
说明 |
|---|---|
expr |
需要被转换类型的值。 |
type |
指定转换的类型,signed,unsigned,decimal,douoble,date,char |
警告
使用CAST将值转为unsinged,值必须是正整型、正整型字符串和正浮点型,且其值小于等于2^64 - 1; 不支持负值
oracle的CAST函数转换成signed,unsigned类型时会四舍五入
mysql的char转换成varchar2(4000),mysql的char的长度是字符长度,而oracle的varchar2是字节长度。char对应数据的字节长度超过4000不支持
示例
-- 转换前MySQL SQL:
SELECT cast('312' as SIGNED) from dual;
+-----------------------+
| cast('312' as SIGNED) |
+-----------------------+
| 312 |
+-----------------------+
SELECT cast(0.55 as UNSIGNED) from dual;
+------------------------+
| cast(0.55 as UNSIGNED) |
+------------------------+
| 1 |
+------------------------+
SELECT cast('hello' as CHAR) from dual;
+-----------------------+
| cast('hello' as CHAR) |
+-----------------------+
| hello |
+-----------------------+
-- 转换后Oracle19C SQL:
SELECT CAST('312' AS number(20,0)) FROM dual;
CAST('312'ASNUMBER(20,0))|
-------------------------+
312|
SELECT CAST(0.55 AS number(20,0)) FROM dual;
CAST(0.55ASNUMBER(20,0))|
------------------------+
1|
SELECT CAST('hello' AS varchar2(4000)) FROM dual;
CAST('HELLO'ASVARCHAR2(4000))|
-----------------------------+
hello |
1.3.3.2.3.3.5. CONCAT
- 语法
CONCAT (str1, str2, ...)- 描述
- 将入参字符串拼接在一起。
参数解释
参数 |
说明 |
|---|---|
str |
需要拼接的字符串,该参数为字符串数据类型 |
警告
由于Oracle19C中无法区分空串与NULL,所以在Oracle19C中,只能将’’与NULL一视同仁来处理
MySQL的函数参数如果有NULL则会返回NULL,而oracle不会
示例
-- 转换前MySQL SQL:
select concat('123', 'abcAA', 'nihao') from dual;
+---------------------------------+
| concat('123', 'abcAA', 'nihao') |
+---------------------------------+
| 123abcAAnihao |
+---------------------------------+
select concat('123', '', 'nihao') from dual;
+----------------------------+
| concat('123', '', 'nihao') |
+----------------------------+
| 123nihao |
+----------------------------+
select concat('123', NULL, 'nihao') from dual;
+------------------------------+
| concat('123', NULL, 'nihao') |
+------------------------------+
| NULL |
+------------------------------+
select concat('123abc') from dual;
+------------------+
| concat('123abc') |
+------------------+
| 123abc |
+------------------+
-- 转换后Oracle19C SQL:
SELECT concat(concat('123', 'abcAA'), 'nihao') FROM dual;
CONCAT(CONCAT('123','ABCAA'),'NIHAO')|
-------------------------------------+
123abcAAnihao |
SELECT concat(concat('123', ''), 'nihao') FROM dual;
CONCAT(CONCAT('123',''),'NIHAO')|
--------------------------------+
123nihao |
SELECT concat(concat('123', NULL), 'nihao') FROM dual;
CONCAT(CONCAT('123',NULL),'NIHAO')|
----------------------------------+
123nihao |
SELECT concat('123abc', '') FROM dual;
CONCAT('123ABC','')|
-------------------+
123abc |
1.3.3.2.3.3.6. GROUP_CONCAT
- 语法
GROUP_CONCAT ([DISTINCT] column_name… [ORDER BY ASC/DESC column_name] [Separator sep_str])- 描述
- 将来自多个行的列值组合成一个单独的字符串,每个值之间可以用分隔符隔开。
参数解释
参数 |
说明 |
|---|---|
column_name |
需要拼接的字符串列,该参数为字符串数据类型 |
sep_str |
分割标识符 |
警告
GROUP_CONCAT函数与listagg函数拼接顺序不完全一致
暂时不支持和keep、over联合使用和聚合函数使用时不支持嵌套使用
GROUP BY分组顺序存在不一致的情况
示例
CREATE TABLE sales (
id int,
product VARCHAR(50),
quantity INT,
sale_date varchar(50)
);
INSERT INTO sales VALUES (4, 'Apple', 10, '2023-01-15');
INSERT INTO sales VALUES (4, 'Banana', 5, '2023-01-20');
INSERT INTO sales VALUES (1, 'Orange', 8, '2023-02-01');
INSERT INTO sales VALUES (1, 'Grape', 12, '2023-01-10');
INSERT INTO sales VALUES (3, 'Apple', 3, '2023-03-01');
-- 转换前MySQL SQL:
SELECT id, GROUP_CONCAT( product ORDER BY id SEPARATOR ',') AS products FROM sales GROUP BY id;
id|products |
--+------------+
1|Grape,Orange|
3|Apple |
4|Banana,Apple|
SELECT id, GROUP_CONCAT( product SEPARATOR ',') AS products FROM sales GROUP BY id;
id|products |
--+------------+
1|Orange,Grape|
3|Apple |
4|Apple,Banana|
SELECT id, GROUP_CONCAT(DISTINCT product SEPARATOR ',') AS products FROM sales GROUP BY id;
id|products |
--+------------+
1|Grape,Orange|
3|Apple |
4|Apple,Banana|
-- 转换后Oracle19C SQL:
SELECT id,listagg(product, ',') WITHIN GROUP (ORDER BY id) AS products FROM sales GROUP BY id;
ID|PRODUCTS |
--+------------+
1|Grape,Orange|
3|Apple |
4|Apple,Banana|
SELECT id,listagg(product, ',') AS products FROM sales GROUP BY id;
ID|PRODUCTS |
--+------------+
1|Orange,Grape|
4|Apple,Banana|
3|Apple |
SELECT id,listagg(DISTINCT product, ',') AS products FROM sales GROUP BY id;
ID|PRODUCTS |
--+------------+
1|Grape,Orange|
3|Apple |
4|Apple,Banana|
1.3.3.2.3.3.7. CHAR_LENGTH
- 语法
CHAR_LENGTH (str)- 描述
- 计算字符串的长度
参数解释
参数 |
说明 |
|---|---|
str |
需要计算长度的字符串,该参数为字符串数据类型 |
警告
由于Oracle19C中无法区分空串与NULL,所以在Oracle19C中,只能将’’与NULL一视同仁来处理
示例
-- 转换前MySQL SQL:
SELECT char_length('zhangsan') FROM dual;
+-------------------------+
| char_length('zhangsan') |
+-------------------------+
| 8 |
+-------------------------+
SELECT char_length(NULL) FROM dual;
+-------------------+
| char_length(NULL) |
+-------------------+
| NULL |
+-------------------+
SELECT char_length('') FROM dual;
+-----------------+
| char_length('') |
+-----------------+
| 0 |
+-----------------+
-- 转换后Oracle19C SQL:
SELECT length('zhangsan') FROM dual;
LENGTH('ZHANGSAN')|
------------------+
8|
SELECT length(NULL) FROM dual;
LENGTH(NULL)|
------------+
|
SELECT length('') FROM dual;
LENGTH('')|
----------+
|
1.3.3.2.3.3.8. CONCAT_WS
- 语法
CONCAT_WS (separator, str1, str2, ...)- 描述
- 将入参字符串与字符串分隔符拼接在一起
参数解释
参数 |
说明 |
|---|---|
separator |
用于分割每个字符串的分隔符 |
str |
需要拼接的字符串,该参数为字符串数据类型 |
警告
由于Oracle19C中无法区分空串与NULL,所以在Oracle19C中,只能将’’与NULL一视同仁来处理
Mysql遇到了NULL不会使用连接符,而Oracle19C会使用连接符
示例
CREATE TABLE TEST_CONCATWS (school varchar(96),name varchar(96));
INSERT INTO TEST_CONCATWS VALUES ('hensheng','ZHANGSAN');
INSERT INTO TEST_CONCATWS VALUES ('hafuo','LISI');
INSERT INTO TEST_CONCATWS VALUES (NULL,'WANGWU');
-- 转换前MySQL SQL:
SELECT CONCAT_WS(':',school, name) FROM TEST_CONCATWS;
+-----------------------------+
| CONCAT_WS(':',school, name) |
+-----------------------------+
| hensheng:ZHANGSAN |
| hafuo:LISI |
| WANGWU |
+-----------------------------+
-- 转换后Oracle19C SQL:
SELECT concat(concat(school, ':'), name) FROM TEST_CONCATWS;
CONCAT(CONCAT(SCHOOL,':'),NAME)|
-------------------------------+
hensheng:ZHANGSAN |
hafuo:LISI |
:WANGWU |
1.3.3.2.3.3.9. LEFT
- 语法
LEFT (str, length)- 描述
- 截取指定长度的字符串
参数解释
参数 |
说明 |
|---|---|
str |
被截取的源字符串,该参数为字符串数据类型 |
length |
需要截取的字符串长度,该参数为数值类型 |
示例
-- 转换前MySQL SQL:
SELECT LEFT('nihao', 2) FROM dual;
+------------------+
| LEFT('nihao', 2) |
+------------------+
| ni |
+------------------+
-- 转换后Oracle19C SQL:
SUBSTR('NIHAO',1,2)|
-------------------+
ni |
1.3.3.2.3.3.10. SUBSTRING
- 语法
SUBSTRING (str, pos [, len])- 描述
- 返回 str 的子字符串,起始位置为 pos,长度为 len。
参数解释
参数 |
说明 |
|---|---|
str |
要操作的字符串,支持varchar2、char、clob、number(n,m)类型 |
pos |
整数,子字符串的起始位置 |
len |
正整数,子字符串的长度 |
警告
由于Oracle中无法区分空串与NULL,所以在Oracle 中只能将’’与NULL,都返回NULL。
pos 和 len 仅支持整数或整数字符串。若为浮点数数值将存在差异,mysql为四舍五入,Oracle向下取整。
数据类型隐式转换存在差异会存在截取结果有差异。如char类型、日期类型等。 比如 SUBSTRING(char_col, 5 , 2) ,char_col 为 ‘1,2,3’ ,但 char_col 类型的长度超过 5,而在 Oracle 中由于字符串会视为 ‘1,2,3 ‘ (带有空格补全), PostgreSQL字符串为’1,2,3’。
Oracle 和 PostgreSQL 在数值的内部存储或显示格式上存在差异。如:对于数值 0.01,Oracle 在某些场景(如使用默认格式化规则时)可能将其显示为 .01,而 Mysql 则保留前导 0,显示为 0.01; 对于精度超过38位的数值和Char数据类型存储字符数的数据,两边数据库处理不一致。
示例
-- 转换前Mysql SQL:
SELECT SUBSTRING('abcdefg', 3) as str1,SUBSTRING('abcdefg', 3, 2) as str2,SUBSTRING('abcdefg', -3) as str3,SUBSTRING('abcdefg', 3, -2) as str4;
+-------+------+------+------+
| str1 | str2 | str3 | str4 |
+-------+------+------+------+
| cdefg | cd | efg | |
+-------+------+------+------+
SELECT SUBSTRING(20250217,2,5) as str1, SUBSTRING(2025.0217,1,6) as str2;
+-------+--------+
| str1 | str2 |
+-------+--------+
| 02502 | 2025.0 |
+-------+--------+
-- 转换后Oracle19C SQL:
SELECT substr('abcdefg', CASE WHEN 3=0 THEN NULL ELSE 3 END) AS str1,substr('abcdefg', CASE WHEN 3=0 THEN NULL ELSE 3 END, 2) AS str2,substr('abcdefg', CASE WHEN -3=0 THEN NULL ELSE -3 END) AS str3,substr('abcdefg', CASE WHEN 3=0 THEN NULL ELSE 3 END, -2) AS str4 FROM DUAL;
STR1 STR2 STR3 S
---------------------------- -------- ---------------------------- -
cdefg cd efg
SELECT substr(20250217, CASE WHEN 2=0 THEN NULL ELSE 2 END, 5) AS str1,substr(2025.0217, CASE WHEN 1=0 THEN NULL ELSE 1 END, 6) AS str2 FROM DUAL;
STR1 STR2
-------------------- ------------------------
02502 2025.0
1.3.3.2.3.4. 其它函数
1.3.3.2.3.4.1. STDDEV
- 语法
STDDEV (expr)- 描述
- 计算一组数值的标准差
参数解释
参数 |
说明 |
|---|---|
expr |
用与就算标准差的数值列,或者表达式 |
警告
计算标准差时,Oracle19C数据库stddev_pop函数计算的标准差精度大于Mysql数据库函数stddev函数计算的标准差
示例
CREATE TABLE TEST_STDDEV (id int,value int,value_double double);
INSERT INTO TEST_STDDEV VALUES (1,10,10.0);
INSERT INTO TEST_STDDEV VALUES (1,20,20.0);
INSERT INTO TEST_STDDEV VALUES (1,30,30.0);
-- 转换前MySQL SQL:
SELECT stddev(value), stddev(value_double) FROM TEST_STDDEV;
stddev(value) |stddev(value_double)|
----------------+--------------------+
8.16496580927726| 8.16496580927726|
-- 转换后Oracle19C SQL:
SELECT stddev_pop(value), stddev_pop(value_double) FROM TEST_STDDEV;
STDDEV_POP(VALUE) |STDDEV_POP(VALUE_DOUBLE)|
----------------------------------------+------------------------+
8.16496580927726032732428024901963797322| 8.16496580927726|
1.3.3.2.3.4.2. TRUNCATE
- 语法
TRUNCATE (number, decimal_places)- 描述
- 用于截取指定的位数
参数解释
参数 |
说明 |
|---|---|
number |
被截取的目标数值 |
decimal_places |
为正时,表示截取的小数位数;为负时表示截取整数的位数 |
示例
CREATE TABLE TEST_STDDEV (id int,value int,value_double double);
INSERT INTO TEST_STDDEV VALUES (1,10,10.0);
INSERT INTO TEST_STDDEV VALUES (1,20,20.0);
INSERT INTO TEST_STDDEV VALUES (1,30,30.0);
-- 转换前MySQL SQL:
SELECT TRUNCATE(123.456, -2) FROM dual;
+-----------------------+
| TRUNCATE(123.456, -2) |
+-----------------------+
| 100 |
+-----------------------+
SELECT TRUNCATE(123.456, 0) FROM dual;
+----------------------+
| TRUNCATE(123.456, 0) |
+----------------------+
| 123 |
+----------------------+
SELECT TRUNCATE(123.456, 2) FROM dual;
+----------------------+
| TRUNCATE(123.456, 2) |
+----------------------+
| 123.45 |
+----------------------+
-- 转换后Oracle19C SQL:
SELECT TRUNC(123.456, -2) FROM dual;
TRUNC(123.456,-2)|
-----------------+
100|
SELECT TRUNC(123.456, 0) FROM dual;
TRUNC(123.456,0)|
----------------+
123|
SELECT TRUNC(123.456, 2) FROM dual;
TRUNC(123.456,2)|
----------------+
123.45|
1.3.3.2.3.4.3. DATABASE
- 语法
DATABASE ()- 描述
- 获取数据库名称
示例
-- 转换前MySQL SQL:
SELECT DATABASE() FROM dual;
+------------+
| DATABASE() |
+------------+
| mysql |
+------------+
-- 转换后Oracle19C SQL:
SELECT sys_context('userenv', 'DB_NAME') FROM dual;
SYS_CONTEXT('USERENV','DB_NAME')|
--------------------------------+
test |
1.3.3.2.3.4.4. SCHEMA
- 语法
SCHEMA ()- 描述
- 获取数据库名称
示例
-- 转换前MySQL SQL:
SELECT SCHEMA() FROM dual;
+----------+
| SCHEMA() |
+----------+
| mysql |
+----------+
-- 转换后Oracle19C SQL:
SELECT sys_context('userenv', 'DB_NAME') FROM dual;
SYS_CONTEXT('USERENV','DB_NAME')|
--------------------------------+
test |
1.3.3.2.3.4.5. CONVERT
- 语法
CONVERT (expr, type)CONVERT (expr using transcoding_name)- 描述
- 将expr转换为指定的数据类型或指定的编码类型。
参数解释
参数 |
说明 |
|---|---|
expr |
要转换的表达式 |
type |
指定转换的类型,该参数支持unsigned、signed、date、datetime、decimal数据类型 |
transcoding_name |
指定的编码格式,目前只支持utf8 |
警告
将expr转为singed、unsigned数据类型仅支持整型或整型字符串,且必须在可支持范围内。 若为字符串类型的浮点数,mysql是向下取整,oracle是四舍五入。 unsigned的取值是[0,18446744073709551615],signed的取值是[-9223372036854775808,9223372036854775807]。如果超过这个范围,数据结果将不一致。 如convert(18446744073709551616,unsigned),mysql的值为18446744073709551615,oracle的值为18446744073709551616。
mysql和oracle数据类型存在差异,如
cast('2024-01-31 14:30:00' as date ),mysql的date记录年月日,结果为2024-01-31;oracle的记录年月日时间信息,结果为2024-01-31 14:30:00。表达式expr转为目标数据类型仅支持相同类型或可以隐式转换的数据类型。如非数值字符串转为decimal,oracle会报错
ORA-01722: 无效数字。将表达式expr转换为指定的编码类型,目前只支持utf8。 oracle的convert转换表达式编码时,expr支持的类型是CHAR, VARCHAR2, NVARCHAR2, CLOB, NCLOB,或者可以隐式转换为以上类型。 如果参数expr隐式转换为字符串时,mysql和oracle存在差异,如日期类型转字符串,会受到日期格式的影响。
示例
示例
-- 转换前MySQL SQL:
SELECT CONVERT('你好, world!' USING utf8) AS utf8_value;
+----------------+
| utf8_value |
+----------------+
| 你好, world! |
+----------------+
SELECT CONVERT(1.5,SIGNED) as col_signed;
+------------+
| col_signed |
+------------+
| 2 |
+------------+
SELECT CONVERT(1.5,UNSIGNED) as col_unsigned;
+--------------+
| col_unsigned |
+--------------+
| 2 |
+--------------+
SELECT CONVERT('1.5',SIGNED) as col_signed;
+------------+
| col_signed |
+------------+
| 1 |
+------------+
SELECT CONVERT('1.5',UNSIGNED) as col_unsigned;
+--------------+
| col_unsigned |
+--------------+
| 1 |
+--------------+
SELECT CONVERT(1234,DECIMAL) as col_decimal;
+-------------+
| col_decimal |
+-------------+
| 1234 |
+-------------+
SELECT CONVERT(STR_TO_DATE('2024-01-31 14:30:00', '%Y-%m-%d %H:%i:%s'),DATE) as col_date;
+------------+
| col_date |
+------------+
| 2024-01-31 |
+------------+
SELECT CONVERT(STR_TO_DATE('2024-01-31 14:30:00', '%Y-%m-%d %H:%i:%s'),DATETIME) as col_datetime;
+---------------------+
| col_datetime |
+---------------------+
| 2024-01-31 14:30:00 |
+---------------------+
-- 转换后Oracle19C SQL:
SELECT convert('你好, world!', 'utf8') AS utf8_value FROM DUAL;
UTF8_VALUE
--------------
你好, world!
SELECT CAST(1.5 AS number(20,0)) AS col_signed FROM DUAL;
COL_SIGNED
----------
2
SELECT CAST(1.5 AS number(20,0)) AS col_unsigned FROM DUAL;
COL_UNSIGNED
------------
2
SELECT CAST('1.5' AS number(20,0)) AS col_signed FROM DUAL;
COL_SIGNED
----------
2
SELECT CAST('1.5' AS number(20,0)) AS col_unsigned FROM DUAL;
COL_UNSIGNED
------------
2
SELECT CAST(1234 AS decimal) AS col_decimal FROM DUAL;
COL_DECIMAL
-----------
1234
SELECT CAST(to_date('2024-01-31 14:30:00', 'YYYY-MM-DD HH24:MI:SS') AS date) AS col_date FROM DUAL;
COL_DATE
-------------------
2024-01-31 14:30:00
SELECT CAST(to_date('2024-01-31 14:30:00', 'YYYY-MM-DD HH24:MI:SS') AS timestamp) AS col_datetime FROM DUAL;
COL_DATETIME
---------------------------------------------------------------------------
2024-01-31 14:30:00