1.3.2.2.13. 转换为 MySQL
1.3.2.2.13.1. 字符串函数
1.3.2.2.13.1.1. EMPTY_CLOB
- 语法
EMPTY_CLOB()- 描述
EMPTY_CLOB()是 Oracle 中用于初始化空 CLOB 定位器的函数。Oracle 转 MySQL 8 场景下,统一 SQL 当前并不是把EMPTY_CLOB()作为普通函数直接改写为 MySQL 侧函数或字符串表达式,而是仅对CREATE TABLE语句中的 CLOB 默认值做兼容处理。当列定义命中CLOB DEFAULT empty_clob()时,转换到 MySQL 8 后会去掉DEFAULT empty_clob()默认值,保留既有的CLOB到LONGTEXT类型映射;如果同时存在NOT NULL约束,则保留NOT NULL。- 参数解释
- 无
警告
当前支持范围限定在
CREATE TABLE列定义中的CLOB DEFAULT empty_clob()默认值处理,不表示普通表达式、DML 或 DQL 中的EMPTY_CLOB()函数已直接支持转换。DDL 侧不会输出
DEFAULT ''或CAST('' AS text)。删除DEFAULT empty_clob()是设计行为,用于避免把 Oracle 特有的 LOB 定位器语义扩散到 MySQL 目标端。对于
CLOB DEFAULT empty_clob() NOT NULL场景,DDL 转换后会保留NOT NULL。若后续 insert 语句省略该列,并且转换链路可通过元数据识别该列默认值来自empty_clob(),则 insert 补列路径会补写空串''。BLOB/empty_blob()以及非CLOB DEFAULT empty_clob()的默认值场景不属于本规则范围。
示例
-- 转换前Oracle SQL:
CREATE TABLE t_clob (
id NUMBER,
content CLOB DEFAULT empty_clob()
);
CREATE TABLE t_clob_not_null (
id NUMBER,
content CLOB DEFAULT empty_clob() NOT NULL
);
-- 转换后MySQL SQL:
CREATE TABLE t_clob (
id DECIMAL,
content LONGTEXT
);
CREATE TABLE t_clob_not_null (
id DECIMAL,
content LONGTEXT NOT NULL
);
1.3.2.2.13.1.2. REGEXP_COUNT
- 语法
REGEXP_COUNT(source_char, pattern [, position [, match_param]])- 描述
- 该函数用于返回
pattern在source_char字符串中出现的次数。Oracle 转 MySQL 8 场景下,统一 SQL 不透传 Oracle 原函数名,而是改写为补丁脚本中的兼容函数unisql.regexp_count(input_string, pattern, position, match_param)。转换器会把 Oracle 的 2 到 4 个参数统一补齐为 MySQL 侧 4 个参数:未指定position时补1,未指定match_param时补空串''。
参数解释
参数 |
说明 |
|---|---|
source_char |
用作搜索值的字符表达式,转换后作为 |
pattern |
正则表达式。兼容类型为 |
position |
可选,正整数,指定从 |
match_param |
可选,匹配参数;缺省补 |
转换规则
仅在
Oracle / Oracle 19c -> MySQL 8路径启用该专用转换;其他 MySQL 目标版本走通用函数转换逻辑。参数数量必须为 2 到 4 个,否则转换阶段报参数数量错误。
转换输出固定为 4 参兼容函数调用,例如:
-- 转换前Oracle SQL: SELECT REGEXP_COUNT('123123123', '123') FROM dual; SELECT REGEXP_COUNT('123123123', '123', 2) FROM dual; SELECT REGEXP_COUNT('Oracle ORACLE oracle', 'oracle', 1, 'i') FROM dual; -- 转换后MySQL SQL: SELECT unisql.regexp_count('123123123', '123', 1, '') FROM dual; SELECT unisql.regexp_count('123123123', '123', 2, '') FROM dual; SELECT unisql.regexp_count('Oracle ORACLE oracle', 'oracle', 1, 'i') FROM dual;
pattern为字符串字面量时,转换器会按目标 MySQL 字符串模式处理反斜杠转义,避免 MySQL 默认字符串解析阶段先消费\d、\n等反斜杠序列。当前转换重点是保证 SQL 字符串字面量传入 MySQL 正则引擎后仍保留 Oracle 源 SQL 中的反斜杠字符;Oracle 正则语义与 MySQL ICU 正则语义不属于完全等价关系。source_char为字符串字面量时也会做目标 MySQL 字符串模式感知的反斜杠保护。例如 Oracle 字面量'测试123\n测试456'表示普通反斜杠和字母n,转换到 MySQL 默认字符串模式时会额外转义,避免变成真实换行。source_char或pattern为NULL字面量时会保留NULL语义,不会改写为空串''。若
source_char或pattern是CAST('...' AS ...)/CAST(NULL AS ...)形式,且CAST内部仍是字面量,也会处理内部字面量,再保留CAST结构。若
pattern是列、变量、函数调用或其他动态表达式,则只递归转换表达式本身,不做上述正则字面量改写。
目标侧兼容函数行为
目标侧补丁函数 unisql.regexp_count 的核心实现如下:
input_string、pattern或position任一为NULL时返回NULL。input_string = ''或pattern = ''时返回NULL,用于贴近 Oracle 空串按NULL处理的语义。position < 1时抛出ORA-01428: argument '...' is out of range风格错误。内部使用
SUBSTRING(input_string, position)截取待匹配字符串,再通过 MySQLREGEXP_INSTR循环统计非重叠匹配次数。match_param中i/c按从左到右顺序处理,后出现的大小写选项覆盖前面的选项;m、n会传递给 MySQL 正则匹配;其他字符当前忽略。
match_param 选项说明
选项 |
说明 |
|---|---|
|
指定大小写不敏感匹配。兼容函数会将 |
|
指定大小写敏感匹配。兼容函数会将 |
|
指定多行匹配模式。兼容函数会将 |
|
指定点号匹配换行模式。兼容函数会将 |
match_param 会从左到右归一化:重复的 i、c、m、n 只保留一个;i 与 c 互斥,后出现者覆盖先出现者;未识别字符当前忽略,不按 Oracle 的 x 扩展空白模式处理。
兼容性说明
警告
该实现依赖目标库已安装
unisql.regexp_count补丁函数;如果补丁函数不存在,转换后的 SQL 会在目标库执行时报函数不存在。当前已验证的兼容类型为:
source_char支持CHAR、VARCHAR2、NCHAR、NVARCHAR2、CLOB;pattern支持CHAR、VARCHAR2、NCHAR、NVARCHAR2;position支持NUMBER;match_param支持CHAR、VARCHAR2、NCHAR、NVARCHAR2。实现中先执行
SUBSTRING(input_string, position),再在截取后的字符串上匹配。已验证^与position组合存在差异:REGEXP_COUNT('abcabc', '^abc', 4)在 Oracle 返回0,转换后在 MySQL 返回1。match_param当前只显式处理i、c、m、n。Oracle 的x扩展匹配参数不会按 Oracle 语义完整实现。MySQL ICU 正则引擎与 Oracle 正则引擎不等价。已验证差异包括连续量词报错、多字节字符计数、零长度匹配推进、Unicode escape 范围、单词边界,以及目标库 collation 参与大小写匹配。
pattern是动态表达式时不会做正则字面量反斜杠保护;动态模式本身需要符合目标库正则语法。目标 MySQL 的 collation 会影响正则大小写敏感性;未显式指定
match_param为c时,大小写匹配结果与 Oracle 默认行为不同。
已知差异示例
以下示例基于 Oracle 转 MySQL 8 的 plain SQL 验证结果整理,用于说明已验证的不一致原因。迁移时以业务 SQL、目标库字符集和 collation 为准复核。
场景 |
示例 |
差异说明 |
|---|---|---|
多字节字符与 |
|
已验证案例中,Oracle 对多字节中文字符按字节或编码单元计数;MySQL 8 ICU 正则按 Unicode 字符匹配,因此 MySQL 计数小于 Oracle。 |
可匹配空串的量词 |
|
|
Unicode escape 字符范围 |
|
MySQL ICU 按 Unicode escape 范围识别中文连续片段;Oracle 对 |
默认大小写敏感性 |
|
Oracle 默认大小写敏感;MySQL 受目标列或字符串 collation 影响按大小写不敏感规则匹配。需要大小写敏感时显式使用 |
单词边界 |
|
MySQL ICU 支持 |
|
|
Oracle 固定长度字符类型带入补空格、national character set 或长度语义;MySQL 转换后成为 |
复杂重复量词 |
|
MySQL ICU 对连续量词执行严格语法校验,目标库执行时报 |
示例
-- 转换前Oracle SQL:
SELECT REGEXP_COUNT('abc123def456', '\d+') AS count_digits FROM dual;
SELECT REGEXP_COUNT('Oracle ORACLE oracle', 'oracle', 1, 'i') AS param_i FROM dual;
SELECT REGEXP_COUNT('123123123', '123', 2) AS pos_mid FROM dual;
-- 转换后MySQL SQL:
SELECT unisql.regexp_count('abc123def456', '\\d+', 1, '') AS count_digits FROM dual;
SELECT unisql.regexp_count('Oracle ORACLE oracle', 'oracle', 1, 'i') AS param_i FROM dual;
SELECT unisql.regexp_count('123123123', '123', 2, '') AS pos_mid FROM dual;