You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CONNECT BY PRIOR出现异常,是否属于Oracle Bug?

Oracle拆分字符串重复行与CONNECT BY循环错误解决

问题场景

在Oracle 12c/19c中执行拆分车型油漆选项的SQL时,返回4行冗余结果(期望仅3行);添加ep.car_model = prior ep.car_model约束限制同车型关联后,触发ORA-01436: 用户数据中的CONNECT BY循环错误。

初始SQL

WITH car_paint_options AS (
   SELECT 'Escort'  car_model, 'red,blue' paint_opts FROM dual UNION
   SELECT 'Puma'    car_model, 'black'    paint_opts FROM dual
)
SELECT row_number() over(order by level) rn, level, ep.car_model,
       regexp_substr(ep.paint_opts, '[^,]+', 1, level) paint_opt
FROM   car_paint_options ep
CONNECT BY regexp_substr (ep.paint_opts, '[^,]+', 1, level) is not null

错误返回结果

rn level car_model paint_opt
--- ----- --------- ---------
  1     1 Puma      black
  2     1 Focus     red
  3     2 Focus     blue
  4     2 Focus     blue

期望正确结果

rn level car_model paint_opt
--- ----- --------- ---------
  1     1 Puma      black
  2     1 Focus     red
  3     2 Focus     blue

添加约束后的SQL

WITH car_paint_options AS (
   SELECT 'Escort'  car_model, 'red,blue' paint_opts FROM dual UNION
   SELECT 'Puma'    car_model, 'black'    paint_opts FROM dual
)
SELECT row_number() over(order by level) rn, level, ep.car_model,
       regexp_substr(ep.paint_opts, '[^,]+', 1, level) paint_opt
FROM   car_paint_options ep
CONNECT BY regexp_substr (ep.paint_opts, '[^,]+', 1, level) is not null
       AND ep.car_model = prior ep.car_model

触发的错误信息

ORA-01436: 用户数据中的CONNECT BY循环

问题原因

  1. 初始SQL冗余行原因:未限制CONNECT BY的层级关联范围,导致不同车型的行之间产生交叉关联,生成重复的拆分结果。
  2. 循环错误原因:仅添加ep.car_model = prior ep.car_model时,Oracle无法区分父行与子行的唯一关联关系,同一行会被反复关联,判定为循环。

正确解法

需要在CONNECT BY中同时指定层级数量限制、同车型约束,并通过唯一标识避免循环。以下是两种可行写法:

写法一:用SYS_GUID()避免循环

WITH car_paint_options AS (
   SELECT 'Escort'  car_model, 'red,blue' paint_opts FROM dual UNION
   SELECT 'Puma'    car_model, 'black'    paint_opts FROM dual
)
SELECT row_number() over(order by car_model, level) rn, level, ep.car_model,
       regexp_substr(ep.paint_opts, '[^,]+', 1, level) paint_opt
FROM   car_paint_options ep
CONNECT BY level <= regexp_count(ep.paint_opts, '[^,]+')
       AND ep.car_model = prior ep.car_model
       AND PRIOR SYS_GUID() IS NOT NULL
ORDER BY rn;

写法二:用rowid避免循环

WITH car_paint_options AS (
   SELECT 'Escort'  car_model, 'red,blue' paint_opts FROM dual UNION
   SELECT 'Puma'    car_model, 'black'    paint_opts FROM dual
)
SELECT row_number() over(order by car_model, level) rn, level, ep.car_model,
       regexp_substr(ep.paint_opts, '[^,]+', 1, level) paint_opt
FROM   car_paint_options ep
CONNECT BY level <= regexp_count(ep.paint_opts, '[^,]+')
       AND ep.car_model = prior ep.car_model
       AND PRIOR rowid = ep.rowid
ORDER BY rn;

代码说明

  • level <= regexp_count(ep.paint_opts, '[^,]+'):明确层级数不超过字符串拆分后的元素总数,避免生成多余层级。
  • ep.car_model = prior ep.car_model:限制仅在同一车型的行内进行层级关联,避免跨车型交叉。
  • PRIOR SYS_GUID() IS NOT NULL / PRIOR rowid = ep.rowid:通过唯一标识让Oracle识别父行与子行的唯一关联,防止循环判定。

内容的提问来源于stack exchange,提问作者cartbeforehorse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:58:25