Oracle 正则表达式用法详解+实战案例(运维/数据清洗专用)

一、前言

在日常 Oracle 数据库运维、HIS / 医保系统数据治理、脏数据清洗场景中,普通 LIKEREPLACEINSTR 函数面对不规则空白、特殊字符、混合文本、格式校验等场景往往力不从心。

Oracle 10g 及以上版本全面支持 POSIX 标准正则表达式,提供 5 大核心正则函数,非常适合医疗行业海量基础数据清洗、格式校验、字符串拆分、内容替换等工作。

本文结合医院业务真实场景,整理正则基础语法、5 大核心函数、高频实战案例、踩坑避坑点,可直接复制落地使用。

适用场景:HIS 系统药品名称、诊疗项目、编号、地址、备注等字段脏数据清洗、格式校验、违规字符过滤。

二、前置说明 & 基础元字符

2.1 重要规则

  1. Oracle 正则默认区分大小写 ,可通过匹配模式 i 忽略大小写;

  2. 不推荐使用 \d\s\w 等简写(低版本兼容差),优先使用字符集写法;

  3. 空白字符分为标准空白 (空格、Tab、回车、换行)和全角空格,二者需分开处理;

  4. 编辑器会对动态拼接正则产生语法误报,以数据库实际执行结果为准。

2.2 常用基础元字符

|-------------------|----------------------------|
| 元字符 | 说明 |
| ^ | 匹配字符串开头 |
| $ | 匹配字符串结尾 |
| . | 匹配任意单个字符(默认不匹配换行) |
| + | 前面字符至少出现 1 次 |
| * | 前面字符出现 0 次或多次 |
| [] | 字符集,匹配括号内任意一个字符 |
| [^] | 取反,匹配不在括号内的字符 |
| [\u4e00-\u9fff] | 匹配汉字(Oracle 11gR2+ 推荐) |
| [[:space:]] | POSIX 标准空白:半角空格、Tab、回车、换行 |

三、Oracle 五大正则核心函数总览

Oracle 正则家族共 5 个高频函数,覆盖判断、替换、截取、定位、统计全场景:

|------------------|--------------------|---------------------------|
| 函数 | 核心作用 | 典型业务场景 |
| REGEXP_LIKE | 正则匹配判断(WHERE 条件筛选) | 脏数据筛查、格式校验、判断是否含汉字 / 特殊字符 |
| REGEXP_REPLACE | 正则全局替换 | 清除空白、过滤特殊字符、数据脱敏、脏字符清洗 |
| REGEXP_SUBSTR | 正则截取子串 | 拆分逗号分隔字符串、提取数字 / 编号 |
| REGEXP_INSTR | 获取匹配内容位置 | 定位特殊字符、非法字符下标 |
| REGEXP_COUNT | 统计匹配次数 | 统计符号、汉字、关键字出现次数 |

通用语法格式:

复制代码

REGEXP_XXX(源字符串, 正则表达式 [, 起始位置] [, 匹配序号] [, 匹配模式])

匹配模式:

  • c:区分大小写(默认)

  • i:忽略大小写

  • m:多行模式


四、函数详解 + 实战案例(可直接运行)

4.1 REGEXP_LIKE 正则匹配判断

作用 :用于 WHERE 条件,筛选符合 / 不符合正则规则的数据,数据排查最常用

案例 1:查询字段包含汉字的记录
复制代码

-- 药品名称、项目名称包含汉字(通用标准写法) SELECT * FROM gy_zt02 t WHERE REGEXP_LIKE(t.xmmc, '[\u4e00-\u9fff]');

案例 2:查询纯数字数据(校验编号、金额、数量字段)
复制代码

-- 整行内容为纯数字 SELECT * FROM gy_zt02 t WHERE REGEXP_LIKE(t.gytj, '^[0-9]+$');

案例 3:查询非纯数字脏数据(重点排查)
复制代码

-- 找出包含字母、符号、汉字、空格的异常数据 SELECT * FROM gy_zt02 t WHERE NOT REGEXP_LIKE(t.gytj, '^[0-9]+$') AND t.gytj IS NOT NULL;

案例 4:查询包含标准空白(空格 / Tab / 回车 / 换行)的数据
复制代码

SELECT * FROM gy_ylml l WHERE REGEXP_LIKE(l.dwqc, '[[:space:]]');

案例 5:查询包含字母的数据
复制代码

SELECT * FROM gy_zt02 t WHERE REGEXP_LIKE(t.xmmc, '[A-Za-z]');


4.2 REGEXP_REPLACE 正则替换(数据清洗核心)

作用:全局匹配字符并替换,清洗各类隐形脏字符、多余空格、特殊符号。

案例 1:清除所有标准空白(空格、Tab、回车、换行)
复制代码

-- 更新语句:清除字段内全部标准空白 UPDATE gy_ylml l SET l.dwqc = REGEXP_REPLACE(l.dwqc, '[[:space:]]', '') WHERE REGEXP_LIKE(l.dwqc, '[[:space:]]');

案例 2:单独清除全角空格(高频坑点)

[[:space:]] 无法匹配全角空格 ,使用普通 REPLACE 处理:

复制代码

-- 清除全角空格 CHR(12288) UPDATE gy_ylml l SET l.dwqc = REPLACE(l.dwqc, CHR(12288), '') WHERE INSTR(l.dwqc, CHR(12288)) > 0;

案例 3:清除所有非数字字符(仅保留数字)

适用于金额、数量、流水号字段清洗:

复制代码

SELECT gytj AS 原始值, REGEXP_REPLACE(gytj, '[^0-9]', '') AS 清洗后纯数字 FROM gy_zt02;

案例 4:清除数字、汉字以外的所有特殊符号
复制代码

SELECT xmmc AS 原始名称, REGEXP_REPLACE(xmmc, '[^0-9\u4e00-\u9fff]', '') AS 清洗后名称 FROM gy_zt02;

案例 5:手机号简单脱敏(中间 4 位打码)
复制代码

SELECT REGEXP_REPLACE('13800138000','(^1[0-9]{3})([0-9]{4})([0-9]{4})$','\1****\3') AS 脱敏手机号 FROM DUAL;


4.3 REGEXP_SUBSTR 正则截取子串

作用:按规则提取字符串片段、拆分分隔符文本。

案例 1:提取字符串中的纯数字
复制代码

SELECT REGEXP_SUBSTR('编号:A123456测试', '[0-9]+') AS 提取数字 FROM DUAL;

案例 2:逗号分隔字符串 行转列(经典用法)
复制代码

-- 将 1,2,3,4 拆分为多行数据 SELECT REGEXP_SUBSTR('苹果,香蕉,橘子,葡萄', '[^,]+', 1, LEVEL) AS 拆分结果 FROM DUAL CONNECT BY LEVEL <= REGEXP_COUNT('苹果,香蕉,橘子,葡萄', ',') + 1;


4.4 REGEXP_INSTR 匹配位置查询

作用:返回匹配字符在字符串中的下标,找不到返回 0。

案例:查询第一个数字出现的位置
复制代码

SELECT REGEXP_INSTR('ABCDE12345', '[0-9]') AS 数字起始位置 FROM DUAL;


4.5 REGEXP_COUNT 统计匹配次数

作用:统计指定字符 / 规则在字符串中出现的次数。

案例 1:统计逗号个数
复制代码

SELECT REGEXP_COUNT('101,102,103,104', ',') AS 逗号数量 FROM DUAL;

案例 2:统计字符串中汉字数量
复制代码

SELECT REGEXP_COUNT('测试数据123ABC', '[\u4e00-\u9fff]') AS 汉字个数 FROM DUAL;


五、综合实战:医疗系统脏数据完整清洗流程

针对 gy_ylmlgy_zt02 这类基础表,一套标准清洗流程(先查询预览,再执行更新)。

步骤 1:预览所有含空白的脏数据(安全校验)

复制代码

SELECT dwqc AS 原始内容, REGEXP_REPLACE(dwqc, '[[:space:]]', '') AS 清标准空白, REPLACE(dwqc, CHR(12288), '') AS 清全角空格 FROM gy_ylml WHERE REGEXP_LIKE(dwqc, '[[:space:]]') OR INSTR(dwqc, CHR(12288)) > 0;

步骤 2:分步执行清洗(规避正则拼接报错)

复制代码

-- 第一步:清除标准空白(空格、Tab、回车、换行) UPDATE gy_ylml l SET l.dwqc = REGEXP_REPLACE(l.dwqc, '[[:space:]]', '') WHERE REGEXP_LIKE(l.dwqc, '[[:space:]]'); -- 第二步:清除全角空格 UPDATE gy_ylml l SET l.dwqc = REPLACE(l.dwqc, CHR(12288), '') WHERE INSTR(l.dwqc, CHR(12288)) > 0;

步骤 3:校验清洗结果

复制代码

-- 清洗后,查询是否还存在空白字符 SELECT * FROM gy_ylml l WHERE REGEXP_LIKE(l.dwqc, '[[:space:]]') OR INSTR(l.dwqc, CHR(12288)) > 0;


六、高频踩坑点 & 避坑总结

  1. [[:space:]] 不匹配全角空格 全角空格 CHR(12288) 必须单独用 REPLACE 处理,不要强行正则拼接,易报 ORA-12726 方括号不匹配。

  2. 禁止在 Oracle 使用 \w \d \s 低版本 Oracle 不兼容,\w 会被识别为普通字母 w,统一替换:

    1. \d[0-9]

    2. \w[A-Za-z0-9_]

    3. \s[[:space:]]

  3. 正则拼接字符串编辑器误报 '['||CHR()||'-'||CHR()||']' 语法本身合法,多数是客户端编辑器语法检查异常,优先使用 [\u4e00-\u9fff] 汉字写法。

  4. TRIM 函数局限性 原生 TRIM 仅能清除首尾半角空格,无法处理中间空格、Tab、全角空格、换行,复杂空白必须用正则。

  5. 执行 UPDATE 前务必 SELECT 预览 数据清洗属于高危操作,先查询查看效果,再执行更新,避免批量误改业务数据。


七、常用正则速查表(日常直接复制)

复制代码

-- 1. 判断包含汉字 REGEXP_LIKE(字段, '[\u4e00-\u9fff]') -- 2. 判断纯数字 REGEXP_LIKE(字段, '^[0-9]+$') -- 3. 判断含标准空白 REGEXP_LIKE(字段, '[[:space:]]') -- 4. 清除所有标准空白 REGEXP_REPLACE(字段, '[[:space:]]', '') -- 5. 清除全角空格 REPLACE(字段, CHR(12288), '') -- 6. 只保留数字,清除其余所有字符 REGEXP_REPLACE(字段, '[^0-9]', '')


标签:#Oracle #正则表达式 #数据清洗 #HIS 系统 #数据库运维 #脏数据处理