PAYATHON 2026

如何提取指定 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 参数,或者改用其他方式拆分并提取全部匹配项。

备注:内容仅供参考。