在国产化替代的浪潮下,越来越多的团队把 Oracle 迁移到达梦(DM)数据库。大多数语法都能平滑迁移,但总有一些"隐藏关卡"等着你。
下面这条 SQL,功能是把人员表中逗号分隔的 txx1 字段拆分成多行:
SELECT jxx1, rxx1,
REGEXP_SUBSTR(txx1,'[^,]+',1,LEVEL) AS txx1
FROM t_tb1
WHERE dxx1='123'
AND RYZT='1'
AND jxx1 IS NOT NULL
AND txx1 IS NOT NULL
AND zxx1 IS NULL
CONNECT BY
LEVEL <= LENGTH(txx1)-LENGTH(REPLACE(txx1,',',''))+1
AND PRIOR rxx1 = rxx1
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;
在 Oracle 上跑得好好的,迁到达梦之后执行时间飙升,甚至出现超时。问题出在哪里?
⚠ 痛点一:过滤时机太晚
WHERE 条件本应先于 CONNECT BY 执行,但部分数据库实现里递归展开发生在过滤之前,导致全表参与递归,开销爆炸。
⚠ 痛点二:每行都要计算长度
LENGTH(txx1)-LENGTH(REPLACE(txx1,',','')) 对每一个递归节点都要算两次字符串长度,达梦对此优化不如 Oracle 激进。
⚠ 痛点三:DBMS_RANDOM 代价大
PRIOR DBMS_RANDOM.VALUE 是经典的"打破 CONNECT BY 循环检测"技巧,但随机数生成在达梦中性能开销更大。
⚠ 痛点四:CONNECT BY 非原生优势
达梦对 CONNECT BY 的内部实现与 Oracle 不同,在字符串拆分这类"宽而浅"的场景下,递归 CTE 往往更稳定高效。
如果团队暂时不想大改写法,可以先做以下三处替换,通常能带来明显提升:
WITH T AS (
SELECT JSH, RYBH, TABH
FROM T_RYXX_KSSZSRY
WHERE DWDM='140100111'
AND RYZT='10'
AND JSH IS NOT NULL
AND TABH IS NOT NULL
AND ZZCZJG IS NULL
)
SELECT JSH, RYBH,
REGEXP_SUBSTR(TABH,'[^,]+',1,LEVEL) AS TABH
FROM T
CONNECT BY
LEVEL <= REGEXP_COUNT(TABH, ',') + 1
AND PRIOR RYBH = RYBH
AND PRIOR SYS_GUID() IS NOT NULL;
此方案改动小,兼容性好,适合快速止血。但若数据量大、txx1 字段很长,仍建议升级到方案二。
这是达梦官方更推荐的字符串拆分姿势。用 WITH RECURSIVE 逐位推进游标,完全避开 CONNECT BY 和正则,性能更稳定。
WITH RECURSIVE T (jxx1, rxx1, txx1, POS, VALUE) AS (
-- 锚点:取第一段(逗号前)
SELECT jxx1, rxx1, txx1, 1,
SUBSTR(txx1, 1, INSTR(txx1||',',',')-1)
FROM t_tb1
WHERE dxx1='123'
AND RYZT='1'
AND jxx1 IS NOT NULL
AND txx1 IS NOT NULL
AND zxx1 IS NULL
UNION ALL
-- 递归:依次推进到下一个逗号
SELECT jxx1, rxx1, txx1, POS+1,
SUBSTR(txx1,
INSTR(txx1,',',1,POS)+1,
INSTR(txx1||',',',',1,POS+1)
- INSTR(txx1,',',1,POS)-1)
FROM T
WHERE INSTR(txx1,',',1,POS) > 0
)
SELECT jxx1, rxx1, VALUE AS txx1
FROM T;
核心逻辑是:锚点部分取第一个逗号前的字符串,递归部分每次把游标 POS 加一,用 INSTR 精确定位下一段的起止位置,终止条件是找不到更多逗号为止。
| 维度 | 原始写法 | 方案一 | 方案二(推荐) |
| 达梦兼容性 | 一般 | 较好 | 最佳 |
| 大数据量性能 | 慢 | 中等 | 快 |
| 改动幅度 | — | 小 | 中等 |
| 可读性 | 中等 | 较好 | 清晰(显式游标) |
| 依赖正则 | 是 | 是 | 否(纯字符函数) |
| 适用场景 | Oracle 原生 | 快速止血 | 生产首选 |
国产化迁移不只是"换个驱动",执行引擎的内部实现差异,才是那些"莫名其妙变慢"的真正元凶。遇到性能骤降,先看递归和正则,往往能快速定位。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/10201716/viewspace-3174286/ ,如需转载,请注明出处,否则将追究法律责任。