1.3.2.2.12. 转换为 goldendb-Mysql

1.3.2.2.12.1. 转换函数

1.3.2.2.12.1.1. TO_NUMBER

语法
TO_NUMBER(expr)
TO_NUMBER(expr,fmt)
描述
该函数功能是将 CHAR、VARCHAR2等类型的字符串转换为 NUMBER 数值数据类型的值

参数解释

参数

说明

expr

必填参数,属于 CHAR、VARCHAR2、NCHAR、NVARCHAR2、BINARY_FLOAT 或 BINARY_DOUBLE 数据类型的数值。

fmt

可选参数,格式模型(format model),仅当 expr 是字符类型时可用。用于指定字符串的数字格式(如 ‘9G999D99’)

警告

  1. goldendb-mysql,TO_NUMBER(expr, fmt, nlsparam) 3参数调用,第 3 参数(NLS),统一sql解析报错,示例sql如下:

SELECT TO_NUMBER(
    '-AusDollars100',
    'L9G999D99',
    'NLS_NUMERIC_CHARACTERS=".,", NLS_CURRENCY="AusDollars"'
) AS "Amount"
FROM DUAL;
  1. goldendb-mysql,参数expr DEFAULT … ON CONVERSION ERROR,统一 sql 解析报错,sql 示例如下:

select TO_NUMBER('abc' DEFAULT 0 ON CONVERSION ERROR) from dual;
  1. 在goldendb-mysql,参数fmt 不支持 FM(填充模式),sql示例如下:

select TO_NUMBER('123.40', 'FM999.99') from dual;
  1. 在goldendb-mysql,参数fmt明确支持的取值范围如下:

元素

例子

基础数字占位符9

999.99

SELECT TO_NUMBER(‘123.45’, ‘999.99’) AS result FROM dual; 返回 123.45

基础数字占位符0

00.0

SELECT TO_NUMBER(‘12.3’, ‘00.0’) AS result FROM dual; 返回 12.3

固定分隔符(.小数点、,千分位)

9,999.99

SELECT TO_NUMBER(‘1,234.56’, ‘9,999.99’) AS result FROM dual; 返回 1234.56

本地化分隔符G(千分位)+ D(小数点)

9G999D99

SELECT TO_NUMBER(‘1,234.56’, ‘9G999D99’) AS result FROM dual; 返回 1234.56

-符号(显示负数负号)

-负号

SELECT TO_NUMBER(‘-123’, ‘999’) AS result FROM dual; 返回 -123

MI(负号在右侧)

比如999MI

SELECT TO_NUMBER(‘123-‘, ‘999MI’) AS result FROM dual; 返回 -123

固定$符号

$999.99

SELECT TO_NUMBER(‘$123.45’, ‘$999.99’) AS result FROM dual;返回123.45

科学计数法E格式

9.99EEEE

SELECT TO_NUMBER(‘1.23E+02’, ‘9.99EEEE’) FROM DUAL;返回123

示例

-- 转换前Oracle SQL:
SELECT TO_NUMBER('0123456'),TO_NUMBER('1.2'),TO_NUMBER('0'),TO_NUMBER(1.2),TO_NUMBER('-1'),TO_NUMBER(-1) FROM DUAL;
TO_NUMBER('0123456') TO_NUMBER('1.2') TO_NUMBER('0') TO_NUMBER(1.2) TO_NUMBER('-1') TO_NUMBER(-1)
-------------------- ---------------- -------------- -------------- --------------- -------------
            123456              1.2              0            1.2             -1            -1

-- 转换后goldendb-MySQL:
SELECT TO_NUMBER('0123456'),TO_NUMBER('1.2'),TO_NUMBER('0'),TO_NUMBER(1.2),TO_NUMBER('-1'),TO_NUMBER(-1) FROM DUAL;
+----------------------+------------------+----------------+----------------+-----------------+---------------+
| TO_NUMBER('0123456') | TO_NUMBER('1.2') | TO_NUMBER('0') | TO_NUMBER(1.2) | TO_NUMBER('-1') | TO_NUMBER(-1) |
+----------------------+------------------+----------------+----------------+-----------------+---------------+
|               123456 |              1.2 |              0 |            1.2 |              -1 |            -1 |
+----------------------+------------------+----------------+----------------+-----------------+---------------+

1.3.2.2.12.2. 字符函数

1.3.2.2.12.2.1. LTRIM

语法
LTRIM(expr)
LTRIM(expr,trim_str)
描述
该函数功能从expr字符串左侧开始,移除属于 trim_str 中任意字符集合的字符,直到遇到非 trim_str 集合字符为止,返回处理后的新字符串。默认是删除expr左侧的空格字符。

参数解释

参数

说明

expr

必填参数,属于 CHAR、VARCHAR2、NCHAR、NVARCHAR2、CLOB、NCLOB 字符数据类型或可隐式转换为字符串的表达式。

trim_str

可选参数,字符数据类型或可隐式转换为字符串的表达式。

警告

  1. goldendb-mysql,字符数据类型CHAR、VARCHAR、TEXT、CLOB、LONGTEXT,比较时自动忽略右侧的尾随空格,示例sql如下:

create table testCharacter(id int,col1 longtext,col2 longtext);
insert into testCharacter(id,col1,col2) values(1,'1 ','1');
insert into testCharacter(id,col1,col2) values(2,'  1','1');
select id,col1=col2  from testCharacter;
 id|col1=col2|
 --+---------+
 1|        1|
 2|        0|
  1. LTRIM函数的参数可以是可隐式转换为字符串的表达式,源库、目标库隐式转化规则有所差异,目前支持整数类型:

-- 转换前Oracle SQL:
SELECT LTRIM(123 ,1),LTRIM(1.23 ,1.0) from DUAL
LTRIM(123,1)|LTRIM(1.23,1.0)|
------------+---------------+
23          |.23            |

-- 转换后goldendb-MySQL:
SELECT unisql.LTRIM(123, 1),unisql.LTRIM(1.23, 1.0) FROM dual;
unisql.LTRIM(123, 1)|unisql.LTRIM(1.23, 1.0)|
--------------------+-----------------------+
23                  |23                     |
  1. 源库和目标库的转义字符不同,影响函数转化结果

-- 转换前Oracle SQL:
SELECT '\' from DUAL
'\'|
---+
\  |

-- goldendb-MySQL需要转化:
SELECT '\\' from DUAL
\|
-+
\|
  1. 考虑到客户的实际使用,在目标库中使该函数的所有入参类型为varchar或可隐式转换为varchar的相关类型,支持的最大字符长度为16383

示例

-- 转换前Oracle SQL:
SELECT LTRIM(' unisql'),LTRIM('lgunisql', 'gl')  from dual;
LTRIM('UNISQL')|LTRIM('LGUNISQL','GL')|
---------------+----------------------+
unisql         |unisql                |

-- 转换后goldendb-MySQL:
SELECT LTRIM(' unisql'),unisql.LTRIM('lgunisql', 'gl') FROM dual
LTRIM(' unisql')|unisql.LTRIM('lgunisql', 'gl')|
----------------+------------------------------+
unisql          |unisql                        |

1.3.2.2.12.2.2. RTRIM

语法
RTRIM(expr)
RTRIM(expr,trim_str)
描述
该函数功能从expr字符串右侧开始,移除属于 trim_str 中任意字符集合的字符,直到遇到非 trim_str 集合字符为止,返回处理后的新字符串。默认是删除expr右侧的空格字符。

参数解释

参数

说明

expr

必填参数,属于 CHAR、VARCHAR2、NCHAR、NVARCHAR2、CLOB、NCLOB 字符数据类型或可隐式转换为字符串的表达式。

trim_str

可选参数,字符数据类型或可隐式转换为字符串的表达式。

警告

  1. goldendb-mysql,字符数据类型CHAR、VARCHAR、TEXT、CLOB、LONGTEXT,比较时自动忽略右侧的尾随空格,示例sql如下:

create table testCharacter(id int,col1 longtext,col2 longtext);
insert into testCharacter(id,col1,col2) values(1,'1 ','1');
insert into testCharacter(id,col1,col2) values(2,'  1','1');
select id,col1=col2  from testCharacter;
 id|col1=col2|
 --+---------+
 1|        1|
 2|        0|
  1. RTRIM函数的参数可以是可隐式转换为字符串的表达式,源库、目标库隐式转化规则有所差异,目前支持整数类型:

-- 转换前Oracle SQL:
SELECT RTRIM(321 ,1),RTRIM(32.1 ,1.0) from DUAL
RTRIM(321,1)|RTRIM(32.1,1.0)|
------------+---------------+
32          |32.            |

-- 转换后goldendb-MySQL:
SELECT unisql.RTRIM(321 ,1),unisql.RTRIM(32.1 ,1.0) FROM dual;
unisql.RTRIM(321 ,1)|unisql.RTRIM(32.1 ,1.0)|
--------------------+-----------------------+
32                  |32                     |
  1. 源库和目标库的转义字符不同,影响函数转化结果

-- 转换前Oracle SQL:
SELECT '\' from DUAL
'\'|
---+
\  |

-- goldendb-MySQL需要转化:
SELECT '\\' from DUAL
\|
-+
\|
  1. 考虑到客户的实际使用,在目标库中使该函数的所有入参类型为varchar或可隐式转换为varchar的相关类型,支持的最大字符长度为16383

示例

-- 转换前Oracle SQL:
SELECT RTRIM('unisql   '),RTRIM('unisqles', 'se') from DUAL
RTRIM('UNISQL')|RTRIM('UNISQLES','SE')|
---------------+----------------------+
unisql         |unisql                |

-- 转换后goldendb-MySQL:
SELECT RTRIM('unisql   '),unisql.RTRIM('unisqles', 'se') FROM dual
RTRIM('unisql   ')|unisql.RTRIM('unisqles', 'se')|
------------------+------------------------------+
unisql            |unisql                        |

1.3.2.2.12.2.3. SUBSTR

语法

SUBSTR(str, pos)
SUBSTR(str, pos, len)
描述
返回 str 的子字符串,起始位置为 pos,长度为 len。参数中包含 NULL 时,返回 NULL

参数解释

参数

说明

str

要操作的字符串

pos

子字符串的起始位置

len

子字符串的长度

警告

  • Oracle 和 GoldenDB-MySQL 在数值的内部存储和显示格式上存在差异。例如,对于数值 0.01,Oracle 在某些情况下(如使用默认格式化规则时)可能显示为 .01,而 GoldenDB-MySQL 则保留前导 0,显示为 0.01。此外,对于精度超过 38 位的数值和 Char 数据类型存储固定字符数的数值,两者的处理方式不一致。

  • 日期类型的行为受日期格式影响,不同的日期格式可能导致 GoldenDB-MySQL 和 Oracle 的行为不一致。

  • 在 GoldenDB-MySQL 中, poslen 类型为整数。当处理浮点数时,Oracle 和 GoldenDB-MySQL 都会隐式转换为整数。然而,Oracle 向零取整,而 GoldenDB-MySQL 则是四舍五入。

  • 在 GoldenDB-MySQL 中,null 和空字符串不相等,而在 Oracle 中,null 和空字符串被视为相等,均为 null。

  • poslen 参数不支持空字符串。

示例

-- 转换前Oracle SQL:
SELECT SUBSTR('abcdefg', 3),SUBSTR('abcdefg', 3, 2),SUBSTR('abcdefg', -3),SUBSTR('abcdefg', 3, -2) FROM DUAL;
-------------------+---------------------+--------------------+----------------------+
SUBSTR('ABCDEFG',3)|SUBSTR('ABCDEFG',3,2)|SUBSTR('ABCDEFG',-3)|SUBSTR('ABCDEFG',3,-2)|
-------------------+---------------------+--------------------+----------------------+
cdefg              |cd                   |efg                 |                      |

select substr (20250217,2,5), substr (2025.0217,1,6) from DUAL;
SUBSTR(20250217,2,5)|SUBSTR(2025.0217,1,6)|
--------------------+---------------------+
02502               |2025.0               |

-- 转换后goldendb-mysql SQL:
 SELECT unisql.substr('abcdefg', 3, length('abcdefg')),unisql.substr('abcdefg', 3, 2),unisql.substr('abcdefg', -3, length('abcdefg')),unisql.substr('abcdefg', 3, -2) FROM DUAL;
 +------------------------------------------------+--------------------------------+-------------------------------------------------+---------------------------------+
 | unisql.substr('abcdefg', 3, length('abcdefg')) | unisql.substr('abcdefg', 3, 2) | unisql.substr('abcdefg', -3, length('abcdefg')) | unisql.substr('abcdefg', 3, -2) |
 +------------------------------------------------+--------------------------------+-------------------------------------------------+---------------------------------+
 | cdefg                                          | cd                             | efg                                             |                                 |
 +------------------------------------------------+--------------------------------+-------------------------------------------------+---------------------------------+

 SELECT unisql.substr(20250217, 2, 5),unisql.substr(2025.0217, 1, 6) FROM DUAL;
 +-------------------------------+--------------------------------+
 | unisql.substr(20250217, 2, 5) | unisql.substr(2025.0217, 1, 6) |
 +-------------------------------+--------------------------------+
 | 02502                         | 2025.0                         |
 +-------------------------------+--------------------------------+

1.3.2.2.12.3. 数值函数

1.3.2.2.12.3.1. TRUNC

语法
TRUNC (numeric[,precision])
描述
该函数返回参数 numeric 按精度 precision 截取后的值

参数解释

参数

说明

numeric

表示被截取的数字,数字类型

precision

表示精度,整型,为可选项,默认值为 0

示例

-- 转换前Oracle SQL:
SELECT TRUNC(555.666,2.2),TRUNC(555.666,-2),TRUNC(555.666) FROM DUAL;
------------------+-----------------+--------------+
TRUNC(555.666,2.2)|TRUNC(555.666,-2)|TRUNC(555.666)|
------------------+-----------------+--------------+
            555.66|              500|           555|

-- 转换后goldendb-MySQL:
SELECT TRUNC(555.666, 2.2),TRUNC(555.666, -2),TRUNC(555.666) FROM DUAL
TRUNC(555.666, 2.2)|TRUNC(555.666, -2)|TRUNC(555.666)|
-------------------+------------------+--------------+
            555.66|               500|           555|

1.3.2.2.12.4. 时间日期函数

1.3.2.2.12.4.1. TRUNC

语法
TRUNC(date,[fmt])
描述
该函数返回以参数 fmt 为单位距离的离指定日期 date 最近的日期时间值,并且返回的日期值在 date 之前

参数解释

参数

说明

date

日期时间类型

fmt

指定了函数返回值与 date 的距离单位,现支持DAY、MONTH、YEAR

示例

-- 转换前Oracle SQL:
SELECT TRUNC(TO_DATE('2022/04/19 10:32:34', 'YYYY/MM/DD HH24:MI:SS'), 'YEAR'),TRUNC(TO_DATE('2022/04/19 10:32:34', 'YYYY/MM/DD HH24:MI:SS'), 'MONTH'),TRUNC(TO_DATE('2022/04/19 10:32:34', 'YYYY/MM/DD HH24:MI:SS'), 'DAY')FROM DUAL;
TRUNC(TO_DATE('2022/04/1910:32:34','YYYY/MM/DDHH24:MI:SS'),'YEAR')|TRUNC(TO_DATE('2022/04/1910:32:34','YYYY/MM/DDHH24:MI:SS'),'MONTH')|TRUNC(TO_DATE('2022/04/1910:32:34','YYYY/MM/DDHH24:MI:SS'),'DAY')|
------------------------------------------------------------------+-------------------------------------------------------------------+-----------------------------------------------------------------+
                                           2022-01-01 00:00:00.000|                                            2022-04-01 00:00:00.000|                                          2022-04-17 00:00:00.000|

-- 转换后GaussDB-Oracle SQL:
SELECT TRUNC(CAST(str_to_date('2022/04/19 10:32:34', '%Y/%m/%d %H:%i:%s') AS DATETIME), 'YEAR'),TRUNC(CAST(str_to_date('2022/04/19 10:32:34', '%Y/%m/%d %H:%i:%s') AS DATETIME), 'MONTH'),TRUNC(CAST(str_to_date('2022/04/19 10:32:34', '%Y/%m/%d %H:%i:%s') AS DATETIME), 'DAY') FROM DUAL
TRUNC(CAST(str_to_date('2022/04/19 10:32:34', '%Y/%m/%d %H:%i:%s') AS DATETIME), 'YEAR')|TRUNC(CAST(str_to_date('2022/04/19 10:32:34', '%Y/%m/%d %H:%i:%s') AS DATETIME), 'MONTH')|TRUNC(CAST(str_to_date('2022/04/19 10:32:34', '%Y/%m/%d %H:%i:%s') AS DATETIME), 'DAY')|
----------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------+
                                                                 2022-01-01 00:00:00.000|                                                                  2022-04-01 00:00:00.000|                                                                2022-04-17 00:00:00.000|

1.3.2.2.12.5. 正则函数

1.3.2.2.12.5.1. REGEXP_REPLACE

语法

REGEXP_REPLACE(source_char, pattern
              [, replace_string
                 [, position
                   [, occurrence
                     [, match_param ]
                   ]
                 ]
              ]
            )
描述
该函数将字符串 source_char 中与正则表达式相匹配的字符替换为 replace_string 中的字符。

参数解释

参数

说明

source_char

必填参数,指定用作搜索值的字符表达式。它通常是一种字符列。数据类型可以是 CHAR、VARCHAR2、NCHAR、NVARCHAR2 或 CLOB 。

pattern

必填参数,指定正则表达式,它通常是一个文本文字,数据类型可以是 CHAR、VARCHAR2、NCHAR 或 NVARCHAR2。。

replace_string

表示替换的字符,可以是 CHAR、VARCHAR2、NCHAR、NVARCHAR2 或 CLOB 类型。

position

开始匹配的位置(可选,默认1)

occurrence

替换的匹配项次数(可选,默认0表示全部替换)

match_param

匹配参数(可选,默认空串’’表示区分大小写、单行模式)

1.3.2.2.12.5.1.1. match_param 取值说明

参数match_param取值

说明

i

表示大小写不敏感。

c

表示大小写敏感。

n

表示句点 . 可以匹配换行符。

m

表示多行模式。

x

表示忽略空格字符,默认情况下,空格字符会相互匹配。goldendb-mysql不支持参数值x

警告

  1. Oracle REGEXP_REPLACE 参数数量限制:2~6个,若不足6个,统一sql转换后是固定6个参数,示例如下

-- 转换前Oracle,3个参数

SELECT REGEXP_REPLACE('12345', '[0-9]', '#') AS result FROM dual;

-- 执行结果如下
SQL> SELECT REGEXP_REPLACE('12345', '[0-9]', '#') AS result FROM dual;

RESUL
-----
#####


-- 转换后goldendb-mysql,固定6个参数,不足的参数取默认值
SELECT REGEXP_REPLACE('12345', '[0-9]', '#', 1, 0, '') AS result FROM dual

-- 执行结果如下:
mysql> SELECT REGEXP_REPLACE('12345', '[0-9]', '#', 1, 0, '') AS result FROM dual;
+--------+
| result |
+--------+
| #####  |
+--------+
1 row in set (0.00 sec)

2.参数2:pattern 限制

    1. 类型必须为ValueExpr(字符串/数值字面量),不支持列、函数、子查询等动态表达式

    1. 统一sql会将Oracle的perl正则语法转换为goldendb-MySQL的POSIX兼容格式,支持的perl正则范围,\d\D\w\W\s\S\A\Z

  • 3.支持的sql用例

-- 转换前Oracle
SELECT REGEXP_REPLACE('Oracle123MySQL456', '\d+', '数字') FROM dual;

-- 转换后goldendb-mysql,将\d转换到[[:digit:]]

mysql> SELECT REGEXP_REPLACE('Oracle123MySQL456', '[[:digit:]]+', '数字', 1, 0, '') FROM dual;
+-------------------------------------------------------------------------+
| REGEXP_REPLACE('Oracle123MySQL456', '[[:digit:]]+', '数字', 1, 0, '')   |
+-------------------------------------------------------------------------+
| Oracle数字MySQL数字                                                     |
+-------------------------------------------------------------------------+
1 row in set (0.00 sec)
  • 4.不支持的sql用例

-- 这个oracle语法在统一sql转换报错
SELECT REGEXP_REPLACE(t_table.source_col, t_table.pattern_col, '替换值') FROM t_table;

-- 报错内容为,[LTU00008]函数参数错误: 函数 regexp_replace 的参数2(pattern)类型非法:实际类型为 *ast.ColumnNameExpr,仅支持值表达式(ValueExpr)。
-- 错误原因:pattern为列表达式(t_table.pattern_col),非ValueExpr,不支持

-- 这个oracle语法在统一sql转换报错
SELECT REGEXP_REPLACE('abc123def', SUBSTR('\d+', 1, 2), '数字') FROM dual;

-- 报错内容为,[LTU00008]函数参数错误: 函数 regexp_replace 的参数2(pattern)类型非法:实际类型为 *ast.FuncCallExpr,仅支持值表达式(ValueExpr)。
-- 错误原因:pattern为函数调用(SUBSTR('\d+',1,2)),非ValueExpr,不支持

-- 这个oracle语法在统一sql转换报错
SELECT REGEXP_REPLACE('abc123def', SUBSTR('\d+', 1, 2), '数字') FROM dual;

-- 报错内容为,[LTU00008]函数参数错误: 函数 regexp_replace 的参数2(pattern)类型非法:实际类型为 *ast.SubqueryExpr,仅支持值表达式(ValueExpr)。

-- 错误原因:pattern为子查询(SELECT '\d+' FROM dual),非ValueExpr,不支持

3.参数3:replace_string 限制

    1. 类型必须为ValueExpr(字符串/数值字面量),不支持动态表达式

    1. 仅处理1-9的反向引用(1-9),转换为MySQL的$1-$9,不支持10+(Oracle本身不支持)

    1. 若参数缺失,默认补空串

  • sql示例如下:

-- 转换前sql
SELECT REGEXP_REPLACE('姓名:张三,年龄:25', '姓名:(\w+),年龄:(\d+)', '\2(\1岁)') FROM dual;

-- 转换后sql和执行结果
mysql> SELECT REGEXP_REPLACE('姓名:张三,年龄:25', '姓名:([[:alnum:]_]+),年龄:([[:digit:]]+)', '$2($1岁)', 1, 0, '') FROM dual;
+----------------------------------------------------------------------------------------------------------------------+
| REGEXP_REPLACE('姓名:张三,年龄:25', '姓名:([[:alnum:]_]+),年龄:([[:digit:]]+)', '$2($1岁)', 1, 0, '')              |
+----------------------------------------------------------------------------------------------------------------------+
| 25(张三岁)                                                                                                         |
+----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

-- 错误原因:replace_string为列表达式(t_table.replace_col),非ValueExpr,不支持
SELECT REGEXP_REPLACE(t_table.source_col, '(\d+)', t_table.replace_col) FROM t_table;

-- 错误原因:replace_string为函数调用(CONCAT('\1', '替换')),非ValueExpr,不支持
SELECT REGEXP_REPLACE('abc123def', '(\d+)', CONCAT('\1', '替换')) FROM dual;

-- 错误原因:replace_string为子查询(SELECT '\1替换' FROM dual),非ValueExpr,不支持
SELECT REGEXP_REPLACE('abc123def', '(\d+)', (SELECT '\1替换' FROM dual)) FROM dual;
  1. Oracle 与 GoldenDB MySQL 中 REGEXP_REPLACE 函数处理反斜杠时的行为差异。

    1. oracle 执行语句 SELECT REGEXP_REPLACE('abc\def', '\\') AS result FROM dual; 返回 abcdef

    1. goldendb mysql 执行语句 SELECT REGEXP_REPLACE('abc\def', '\\') AS result FROM dual; 返回错误 Unrecognized escape sequence in regular expression.

    1. GoldenDB MySQL 中反斜杠的转义规则

    • 字符串层:要表示1个实际的 \,单引号内需要写 \\ (因为 MySQL 字符串会把 \\ 解析为 1 个 \

    • 正则层:正则中 \ 是转义符,要匹配1个实际的 \ ,正则模式需要写 \\

    • 叠加后:正则模式本身是字符串,因此需要写 \\\\ (字符串层解析为 \\ ,正则层再解析为 \,最终匹配 1 个实际的 \)。

  1. 参数6:match_param取值限制

    • 参数6match_param取值x在goldendb-mysql执行报错,具体报错sql和报错信息示例如下:

    mysql> SELECT REGEXP_REPLACE('a b c', 'a b c', 'X', 1, 1, 'x');
    ERROR 1210 (HY000): Incorrect arguments to regexp_replace
    

示例

-- 转换前Oracle SQL:
SELECT REGEXP_REPLACE('china', '(.)', '\1 '),REGEXP_REPLACE('Jane Doe','Jane', 'John'),REGEXP_REPLACE('515.123.4444','([[:digit:]]{3})\.([[:digit:]]{3})\.([[:digit:]]{4})','(\1) \2-\3') "REGEXP_REPLACE",REGEXP_REPLACE('500   Oracle     Parkway,    Redwood  Shores, CA','( ){2,}', ' ') FROM DUAL;

REGEXP_REP REGEXP_R REGEXP_REPLACE REGEXP_REPLACE('500ORACLEPARKWAY,REDWO
---------- -------- -------------- --------------------------------------
c h i n a  John Doe (515) 123-4444 500 Oracle Parkway, Redwood Shores, CA

-- 转换后goldendb SQL:
SELECT REGEXP_REPLACE('china', '(.)', '$1 ', 1, 0, ''),REGEXP_REPLACE('Jane Doe', 'Jane', 'John', 1, 0, ''),REGEXP_REPLACE('515.123.4444', '([[:digit:]]{3})\.([[:digit:]]{3})\.([[:digit:]]{4})', '($1) $2-$3', 1, 0, '') AS `REGEXP_REPLACE`,REGEXP_REPLACE('500   Oracle     Parkway,    Redwood  Shores, CA', '( ){2,}', ' ', 1, 0, '') FROM DUAL;
+-------------------------------------------------+------------------------------------------------------+----------------+----------------------------------------------------------------------------------------------+
| REGEXP_REPLACE('china', '(.)', '$1 ', 1, 0, '') | REGEXP_REPLACE('Jane Doe', 'Jane', 'John', 1, 0, '') | REGEXP_REPLACE | REGEXP_REPLACE('500   Oracle     Parkway,    Redwood  Shores, CA', '( ){2,}', ' ', 1, 0, '') |
+-------------------------------------------------+------------------------------------------------------+----------------+----------------------------------------------------------------------------------------------+
| c h i n a                                       | John Doe                                             | (515) 123-4444 | 500 Oracle Parkway, Redwood Shores, CA                                                       |
+-------------------------------------------------+------------------------------------------------------+----------------+----------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

1.3.2.2.12.5.2. REGEXP_SUBSTR

语法

REGEXP_SUBSTR(source_char, pattern
         [, position [, occurrence [,match_param [, subexpr ] ] ] ])
描述
该函数允许使用正则表达式搜索字符串并返回匹配字符串

参数解释

参数

说明

source_char

作为正则匹配的源字符串,即被搜索、截取的目标对象。支持任何字符类型的输入(如 VARCHAR2、CHAR、CLOB 等),为函数必选参数。

pattern

定义匹配规则的正则表达式模式,用于识别源字符串中需要截取的内容。必选参数,通常为文本字面量,可包含正则元字符、子表达式(分组)等

position

可选参数,指定从源字符串的第几个字符开始执行正则匹配,取值是一个正整数。默认值是 1,表示从第一个字符开始搜索

occurrence

可选参数,指定返回源字符串中第 N 个符合 pattern 规则的匹配项。默认值为 1

match_param

可选参数,控制正则匹配的行为模式,可组合多个参数(如 ‘im’)。取值范围见下方match_param 取值说明表格

subexpr

可选参数,指定返回 pattern 中 第 N 个子表达式(分组)的匹配结果。是一个介于 0 到 9 之间的整数, 值为 0 时返回整个正则表达式的匹配结果;值为 1-9 时,返回对应序号分组的匹配内容

1.3.2.2.12.5.2.1. match_param 取值说明

参数match_param取值

说明

i

表示大小写不敏感。

c

大小写敏感匹配(默认)。

n

允许 . 匹配换行符

m

多行模式

x

表示忽略空格字符,默认情况下,空格字符会相互匹配。 goldendb-mysql不支持参数值x

警告

  1. oracle REGEXP_SUBSTR 函数6个参数,统一sql转换后依赖 GoldenDB-MySQL 支持 ‘REGEXP_REPLACE’ 函数的 6 参数语法(source, pattern,replacement, pos, occurrence, match_type),参考 REGEXP_REPLACE

  2. Oracle 与 GoldenDB MySQL 中 REGEXP_REPLACE 函数处理反斜杠时的行为差异。

    • oracle 执行语句 SELECT REGEXP_REPLACE('abc\def', '\\') AS result FROM dual; 返回 abcdef

    • goldendb mysql 执行语句 SELECT REGEXP_REPLACE('abc\def', '\\') AS result FROM dual; 返回错误 Unrecognized escape sequence in regular expression.

    • GoldenDB MySQL 中反斜杠的转义规则

      • 字符串层:要表示1个实际的 \,单引号内需要写 \\ (因为 MySQL 字符串会把 \\ 解析为 1 个 \

      • 正则层:正则中 \ 是转义符,要匹配1个实际的 \ ,正则模式需要写 \\

      • 叠加后:正则模式本身是字符串,因此需要写 \\\\ (字符串层解析为 \\ ,正则层再解析为 \,最终匹配 1 个实际的 \)。

  3. oracle REGEXP_SUBSTR 函数参数个数 2~5,统一sql转换后依赖 GoldenDB-MySQL 支持 ‘REGEXP_REPLACE’ 函数固定5参数语法。

-- oracle语句执行
SQL> SELECT REGEXP_SUBSTR('abc123def', '[0-9]+') FROM DUAL;

REG
---
123

--转换后goldendb-mysql,regexp_substr固定5参数
mysql> SELECT REGEXP_SUBSTR('abc123def', '[0-9]+', 1, 1, '') FROM DUAL;
+------------------------------------------------+
| REGEXP_SUBSTR('abc123def', '[0-9]+', 1, 1, '') |
+------------------------------------------------+
| 123                                            |
+------------------------------------------------+
1 row in set (0.01 sec)
  1. 参数2:pattern 限制如下

    • 类型必须为ValueExpr(字符串/数值字面量),不支持列、函数、子查询等动态表达式

    • 统一sql会将Oracle的perl正则语法转换为goldendb-MySQL的POSIX兼容格式,支持的perl正则范围,\d\D\w\W\s\S\A\Z

    -- 转换失败,函数 regexp_substr 的参数2(pattern)类型非法:实际类型为 *ast.ColumnNameExpr,仅支持值表达式(ValueExpr)
    SELECT REGEXP_SUBSTR('abc', column_name, 1, 1) FROM test_table;
    
  2. 参数6: subexpr说明,goldendb MySQL 原生的 REGEXP_SUBSTR 函数不支持第6个参数(subexpr,即提取指定捕获组),为了在兼容 goldendb MySQL 的语法中实现 Oracle 第6参数的功能,将 Oracle 风格的 6 参数 REGEXP_SUBSTR 转换为 goldendb MySQL 的 REGEXP_REPLACE 调用。参数映射关系如下图:

    oracle参数位置

    Oracle 参数名

    映射目标

    GoldenDB-MySQL 参数位置

    1

    source_char

    REGEXP_REPLACE

    1 source_char

    2

    pattern

    REGEXP_REPLACE

    2 pattern

    3

    position

    REGEXP_REPLACE

    4 position

    4

    occurrence

    REGEXP_REPLACE

    5 occurrence

    5

    match_param

    REGEXP_REPLACE

    6 match_param

    6

    subexpr

    REGEXP_REPLACE

    3 replace_string

    -- oracle执行下面sql
    SQL> SELECT REGEXP_SUBSTR('123-456-7890', '([0-9]{3})-([0-9]{3})-([0-9]{4})', 1, 1, 'c', 2) from dual;
    
    REG
    ---
    456
    
    -- 转换后goldendb-mysql ,6参数的函数reg_replace
    mysql> SELECT regexp_replace('123-456-7890', '([0-9]{3})-([0-9]{3})-([0-9]{4})', '$2', 1, 1, 'c') FROM DUAL;
    +-------------------------------------------------------------------------------------+
    | regexp_replace('123-456-7890', '([0-9]{3})-([0-9]{3})-([0-9]{4})', '$2', 1, 1, 'c') |
    +-------------------------------------------------------------------------------------+
    | 456                                                                                 |
    +-------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
    
     -- 转换报错函数 regexp_substr 的参数6必须是0-9之间的直接整数字面量(用于指定提取的捕获组编号),当前使用的不是合法的整数字面量,建议:使用0-9之间的
     SELECT REGEXP_SUBSTR('123-456', '(\\d+)-(\\d+)', 1, 1, 'c', column_name) FROM test_table;
    
  1. 参数5:match_param取值限制

    • 参数5match_param取值x在goldendb-mysql执行报错,具体报错sql和报错信息示例如下:

    mysql> SELECT REGEXP_SUBSTR('dacdACD', 'a .d', 1, 1, 'x') AS a FROM dual;
    ERROR 1210 (HY000): Incorrect arguments to regexp_substr
    

示例

-- 转换前Oracle SQL:
 SQL> SELECT REGEXP_SUBSTR('500 Oracle Parkway', '[[:alpha:]]+') FROM DUAL;

 REGEXP
 ------
 Oracle

 SQL> select REGEXP_SUBSTR('123-456-7890', '([0-9]{3})-([0-9]{3})-([0-9]{4})', 1, 1, 'c', 2) from dual;

 REG
 ---
 456


 -- 转换后goldendb

 mysql> SELECT REGEXP_SUBSTR('500 Oracle Parkway', '[[:alpha:]]+', 1, 1, '') FROM DUAL;
 +---------------------------------------------------------------+
 | REGEXP_SUBSTR('500 Oracle Parkway', '[[:alpha:]]+', 1, 1, '') |
 +---------------------------------------------------------------+
 | Oracle                                                        |
 +---------------------------------------------------------------+
 1 row in set (0.00 sec)

 mysql> SELECT regexp_replace('123-456-7890', '([0-9]{3})-([0-9]{3})-([0-9]{4})', '$2', 1, 1, 'c') FROM DUAL;
 +-------------------------------------------------------------------------------------+
 | regexp_replace('123-456-7890', '([0-9]{3})-([0-9]{3})-([0-9]{4})', '$2', 1, 1, 'c') |
 +-------------------------------------------------------------------------------------+
 | 456                                                                                 |
 +-------------------------------------------------------------------------------------+
 1 row in set (0.00 sec)

1.3.2.2.12.6. 分析函数

1.3.2.2.12.6.1. ROW_NUMBER

语法

ROW_NUMBER() OVER ([PARTITION BY expr [, ...]] [ORDER BY expr [ASC DESC] [, ...]])

描述

  • 该函数为结果集中的每一行分配一个唯一的、连续的整数(从 1 开始),编号依据 ORDER BY 子句指定的顺序生成。

  • 若使用 PARTITION BY,则在每个分区内独立编号;否则对整个结果集编号。

  • 常用于实现 Top-N 查询、分页、去重、分组取最新记录等场景。

  • ⚠️ 注意:ROW_NUMBER() 是分析函数(Analytic Function),必须与 OVER() 子句一起使用。

参数解释

关键字

说明

PARTITION BY

可选。将输入数据划分为多个逻辑分区,在每个分区内独立计算行号。支持多个表达式,用逗号分隔。

ORDER BY

可选。定义行号分配的排序规则。支持多列、升序(ASC)或降序(DESC)。

expr

表达式

警告

  1. ORDER BY 子句
    • 在 Oracle 中,若省略 ORDER BY,将报错:ORA-30485: missing ORDER BY expression in the window specification

    • 统一 SQL 转换后,GoldenDB-MySQL 不要求ORDER BY 存在。

  2. 不能在 WHERE 子句中直接引用
    • 分析函数在 SELECT 阶段计算,无法在 WHERE 中使用。需通过子查询或 CTE 包装后过滤:

    SELECT FROM (
    SELECT col1, ROW_NUMBER() OVER (ORDER BY col2) AS rn
    FROM table_name
    ) WHERE rn <= 10;
    
  3. 非确定性排序风险
    • 若 ORDER BY 列存在重复值且未包含唯一标识列(如主键),多次执行可能返回不同行号顺序。

    • 建议:在 ORDER BY 中加入唯一列以确保结果可重现:

    ROW_NUMBER() OVER (ORDER BY salary DESC, emp_id ASC)
    
  4. 与 GROUP BY 混用限制
    • 在oracle,若 SELECT 中包含非聚合列(如 salary),但未出现在 GROUP BY 中,则不能与 ROW_NUMBER() 同时使用(报 ORA-00979)。

    • 但若 ROW_NUMBER() 作用于聚合结果(如 ORDER BY AVG(salary)),则是合法的。

    • goldendb-mysql ,不受上面限制,即可以再group by混用的时候,order by 后跟非聚合列。

  5. 物化视图(Materialized View)兼容性
    • Oracle 中含 ROW_NUMBER() 的物化视图 不支持快速刷新(FAST REFRESH),仅支持全量刷新(COMPLETE)。

    • 统一sql解析失败,不支持创建物化视图。

  6. 性能影响
    • 对大数据集,ROW_NUMBER() 需要排序,开销较大。

    • 优化建议:在 ORDER BY 列上创建索引,Oracle 可能使用 WINDOW SORT PUSHED RANK 优化 Top-N 查询。

示例

-- 示例1:基本用法(全局编号)
SELECT employee_id, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn
FROM employees;

转换后sql
SELECT
    employee_id,
    salary,
    ROW_NUMBER() OVER (
        ORDER BY salary DESC
    ) AS rn
FROM employees;

-- 示例2:分组内编号(每部门薪资排名)
SELECT department_id, employee_id, salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC, employee_id) AS rn
FROM employees;

转换后sql
SELECT
    department_id,
    employee_id,
    salary,
    ROW_NUMBER() OVER (
        PARTITION BY department_id
        ORDER BY salary DESC, employee_id
    ) AS rn
FROM
    employees;

-- 示例3:Top-2 高薪员工(每部门)
SELECT department_id, employee_id, salary
FROM (
SELECT department_id, employee_id, salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC, employee_id) AS rn
FROM employees
)
WHERE rn <= 2
ORDER BY department_id, salary DESC;

转换后sql
SELECT
    department_id,
    employee_id,
    salary
FROM
    (
        SELECT
            department_id,
            employee_id,
            salary,
            ROW_NUMBER() OVER (
                PARTITION BY department_id
                ORDER BY salary DESC, employee_id
            ) AS rn
        FROM
            employees
    ) AS uni_sub
WHERE
    rn <= 2
ORDER BY
    department_id,
    salary DESC;

-- 示例4:去重(保留 employee_id 最大的记录)
DELETE FROM employees
WHERE employee_id NOT IN (
SELECT employee_id FROM (
SELECT employee_id,
ROW_NUMBER() OVER (PARTITION BY email ORDER BY employee_id DESC) AS rn
FROM employees
) WHERE rn = 1
);

转换后sql
DELETE FROM
    employees
WHERE
    employee_id NOT IN (
        SELECT
            *
        FROM
            (
                SELECT
                    employee_id
                FROM
                    (
                        SELECT
                            employee_id,
                            ROW_NUMBER() OVER (
                                PARTITION BY email
                                ORDER BY employee_id DESC
                            ) AS rn
                        FROM
                            employees
                    ) AS uni_sub
                WHERE
                    rn = 1
            ) AS unisub
    );

1.3.2.2.12.6.2. TO_CHAR

语法
TO_CHAR(expr)
TO_CHAR(expr,fmt)
描述
该函数功能是将 数值、时间 等类型的数据转换为 字符 类型的值

参数解释

参数

说明

expr

必填参数,属于 timestamp/date/int/number/decimal/float/double 数据类型的数值。

fmt

可选参数,支持时间格式 YYYY/MM/DD/HH/MI/SS/MON,支持数值常量格式 9/0/./FM

警告

  1. 仅支持一个和两个参数的场景;

  2. to_char(null) 在oracle和golden_mysql表现不一致;

  3. to_char的第二个参数仅支持字符串字面量;

  4. to_char第一个参数支持类型timestamp, date, int, number, decimal, float, double, number和decimal需要带精度;

  5. to_char第二个参数支持时间格式 YYYY/YY/MM/DD/HH24/HH12/MI/SS/MON, 数值常量格式 9/0/./FM;

示例

-- 转换前Oracle SQL:
 select to_char(10), to_char(123.45), to_char(1234.56, '99999.999'), to_char(DATE '2023-12-15', 'YYYYDDMM'), to_char(TIMESTAMP '2023-12-15 14:30:45.123456', 'YYYY-MM-DD HH24:MI:SS') FROM dual;
 TO_CHAR(10)|TO_CHAR(123.45)|TO_CHAR(1234.56,'99999.999')|TO_CHAR(DATE'2023-12-15','YYYYDDMM')|TO_CHAR(TIMESTAMP'2023-12-1514:30:45.123456','YYYY-MM-DDHH24:MI:SS')|
 -----------+---------------+----------------------------+------------------------------------+--------------------------------------------------------------------+
 10         |123.45         |  1234.560                  |20231512                            |2023-12-15 14:30:45                                                 |

-- 转换后goldendb-MySQL:
 SELECT to_char(10),to_char(123.45),to_char(1234.56, '99999.999'),to_char(DATE '2023-12-15', 'YYYYDDMM'),to_char(TIMESTAMP '2023-12-15 14:30:45.123456', 'YYYY-MM-DD HH24:MI:SS') FROM dual
 +-------------+-----------------+-------------------------------+----------------------------------------+--------------------------------------------------------------------------+
 | to_char(10) | to_char(123.45) | to_char(1234.56, '99999.999') | to_char(DATE '2023-12-15', 'YYYYDDMM') | to_char(TIMESTAMP '2023-12-15 14:30:45.123456', 'YYYY-MM-DD HH24:MI:SS') |
 +-------------+-----------------+-------------------------------+----------------------------------------+--------------------------------------------------------------------------+
 | 10          | 123.45          |   1234.560                    | 20231512                               | 2023-12-15 14:30:45                                                      |
 +-------------+-----------------+-------------------------------+----------------------------------------+--------------------------------------------------------------------------+