如何提取指定 substring 后的日期值
支付阿杰
结论
在 Oracle 中,可以用正则表达式定位固定标记,再提取标记后、第一个空白字符或 # 之前的内容。假设字段名为 call_log,SQL 可以这样写:
SELECT
REGEXP_SUBSTR(
call_log,
'#Promise to pay on_ #d#([^[:space:]#]+)',
1,
1,
NULL,
1
) AS promise_to_pay_on,
REGEXP_SUBSTR(
call_log,
'#Call later on_ #d#([^[:space:]#]+)',
1,
1,
NULL,
1
) AS call_later_on
FROM call_logs;
返回结果如下:
PROMISE_TO_PAY_ON | CALL_LATER_ON
------------------+--------------
01-JUN | 02-JUN
原理
这两个正则表达式会先匹配对应的固定标记:
#Promise to pay on_ #d#
#Call later on_ #d#
标记后面的捕获组是:
([^[:space:]#]+)
它会连续提取一个或多个非空白且不是 # 的字符,遇到空格、换行或下一个标签时停止匹配。
REGEXP_SUBSTR 的最后一个参数为 1,表示返回第一个捕获组,而不是包含固定标记的完整匹配结果。
转换成日期类型
示例只包含日期和月份,没有年份,因此不能确定唯一的完整日期。如果业务规则要求使用当前年份,可以显式拼接年份:
SELECT
TO_DATE(
REGEXP_SUBSTR(
call_log,
'#Promise to pay on_ #d#([^[:space:]#]+)',
1,
1,
NULL,
1
) || '-' || EXTRACT(YEAR FROM SYSDATE),
'DD-MON-YYYY',
'NLS_DATE_LANGUAGE=English'
) AS promise_to_pay_date
FROM call_logs;
需要注意:
JUN是英文月份缩写,转换时应明确指定NLS_DATE_LANGUAGE=English。- 使用当前年份是一项业务假设。如果日志中有年份字段,应优先使用实际年份。
- 标记不存在时,
REGEXP_SUBSTR会返回NULL。 - 如果同一个标记可能出现多次,需要调整
REGEXP_SUBSTR的 occurrence 参数,或者改用其他方式拆分并提取全部匹配项。
备注:内容仅供参考。
