为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】: DM Database Server 64 V8,DB Version: 0x7000d
【操作系统】:win10 64
【CPU】: 处理器 AMD Ryzen 5 PRO 4650U with Radeon Graphics 2.10 GHz
【问题描述】:select REGEXP_SUBSTR('[2026-07-06 14:23:45] [ERROR] 用户10086下单失败,订单号:ORD-2026-0706-001,错误码:E500,详情:支付网关连接超时(30s),请稍后重试。',
'(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})');
select REGEXP_SUBSTR('[2026-07-06 14:23:45] [ERROR] 用户10086下单失败,订单号:ORD-2026-0706-001,错误码:E500,详情:支付网关连接超时(30s),请稍后重试。',
'[(\w{5})]', 1, 1, '', 1);
select REGEXP_SUBSTR('[2026-07-06 14:23:45] [ERROR] 用户10086下单失败,订单号:ORD-2026-0706-001,错误码:E500,详情:支付网关连接超时(30s),请稍后重试。',
'户(\d{5})下', 1, 1, '', 2);
select REGEXP_SUBSTR('[2026-07-06 14:23:45] [ERROR] 用户10086下单失败,订单号:ORD-2026-0706-001,错误码:E500,详情:支付网关连接超时(30s),请稍后重试。',
':(ORD-\d{4}-\d{4}-\d{3})', 1, 1, '', 2);
select REGEXP_SUBSTR('[2026-07-06 14:23:45] [ERROR] 用户10086下单失败,订单号:ORD-2026-0706-001,错误码:E500,详情:支付网关连接超时(30s),请稍后重试。',
':(E\d{3}),', 1, 1, '', 2); 在以上测试中,第6个参数的和文档描述不符。下面引用deepSeek的说法:感谢你贴出官方文档!这份文档彻底解释清楚了之前所有的困惑。我现在完全明白了,并且发现我之前的解释确实是错的,你的测试结果也是对的,但文档的描述和你的测试结果之间有一个关键细节需要确认。
subexpr:正整数,取值范围为:0~9,表示匹配pattern中的第subexpr个子正则表达式,子正则表达式必须是由括号标记的表达式。如果subexpr=0,则表示匹配整个正则表达式;如果subexpr > 0,则匹配对应的第subexpr个子正则表达式;如果subexpr大于子正则表达式个数或者subexpr为 NULL,则返回 NULL。
() 包起来的才算“子正则表达式”。subexpr=0:返回整个匹配串(默认行为)。subexpr > 子表达式个数:返回 NULL。你的测试:
REGEXP_SUBSTR('...用户10086下单...', '户(\d{5})下', 1, 1, '', 3) -- 返回 '下'
根据文档:
(\d{5}))。subexpr=3,因为 3 > 1,应该返回 NULL。'下'。subexpr 编号规则包含普通字符片段(与文档描述不完全一致)虽然文档说“子正则表达式必须是由括号标记的表达式”,但你的测试结果强烈表明:达梦在实际实现中,可能把整个正则表达式按“连续片段”拆分成多个子表达式,包括普通字符。
比如 '户(\d{5})下' 被拆为:
'户''(\d{5})''下'所以 subexpr=3 返回 '下'。
但这与文档中的“必须是由括号标记的表达式”矛盾。
不同版本的达梦,或者不同编译环境(Windows/Linux),REGEXP_SUBSTR 的行为可能存在细微差异。你用的是哪个版本?是在 Windows 还是 Linux 上跑的?
'户(\d{5})下' 中的 '户' 和 '下' 被解析成某种“隐式子表达式”在 POSIX 正则引擎中,括号 () 确实定义子表达式,但某些引擎在处理 REGEXP_SUBSTR 的 subexpr 参数时,可能会把每个独立的普通字符串片段也视为一个“子匹配项”,虽然它们不是捕获组。
subexpr=0(默认,返回整个匹配)或 subexpr=1(只取第一个括号),避免使用超出捕获组数量的值。'户' 或 '下',直接用 REGEXP_SUBSTR 不带 subexpr 参数,配合 SUBSTR 或 REPLACE 来处理。10086,用 '户(\d{5})下' 配合 subexpr=1 是最稳的。-- 提取用户ID(10086)→ 正确,取第1个括号
REGEXP_SUBSTR(msg, '户(\d{5})下', 1, 1, '', 1) -- 返回 10086
-- 提取整个匹配串(户10086下)→ 正确,subexpr=0 或省略
REGEXP_SUBSTR(msg, '户(\d{5})下', 1, 1, '', 0) -- 返回 户10086下
-- 提取第二个子表达式 → 这里没有第二个括号,按文档应返回 NULL
-- 但你测试返回了 '下',说明实际行为与文档不一致
REGEXP_SUBSTR(msg, '户(\d{5})下', 1, 1, '', 2) -- 文档预期 NULL,你实际测试可能不是
我建议你把这个问题反馈给达梦官方技术支持,或者查阅你当前版本的具体 Release Notes,确认 REGEXP_SUBSTR 的 subexpr 参数是否在某个版本后行为发生了变化。这也是学习数据库时经常会遇到的情况——文档描述和实际行为有时会有偏差,最终还是要靠自己的测试来验证。 😊

先查一下ID_CODE和UNICODE,确认具体的版本号及字符集
SELECT ID_CODE,UNICODE我在自己手头几个不同版本环境里测试,发现在部分版本中,使用UTF8字符集编码情况下能再现问题,而使用GB18030编码没事。
估计要等达梦官方技术人员给出处理方案了。
测试情况如下:

--03134283938-20221019-172201-20018
这是很久前版本,UNICODE值为1和0都能返回正确结果
--03134284132-20231226-213242-20081


能看出UNICODE为1,则结果与贴主情况类似
--03134284552-20260414-322369-20221


这是目前较新版本,也有类似情况