分层查询的奇怪行为

时间:2013-11-19 18:21:48

标签: sql oracle oracle11g

我有一个分层查询,它会多次返回相同的行(by rowid):

select 
    rowid, regexp_substr(col, '[^; ]+', 1, level) data, level
from 
    (select * from table1 where rowid in ('rowid1', 'rowid2'))
connect by 
    regexp_substr(col, '[^; ]+', 1, level) is not null

此查询返回以下结果(摘录):

rowid               data    level
AADAxrADkAACic5AAA  val1    1
AADAxrADkAACic5AAA  val2    2
AADAxrADkAACic5AAA  val3    3
AADAxrADkAACic5AAA  val4    4
AADAxrADkAACic5AAA  val5    5
AADAxrADkAACic5AAA  val6    6

如果同一行是父亲和孩子的话,怎么会发生呢?

另外,如果我想通过rowid限制我想要的孩子:

connect by regexp_substr(col, '[^; ]+', 1, level) is not null and prior rowid = rowid

Oracle告诉我,我的数据中有一个循环?这似乎是合理的,因为我有一个行与父亲和孩子相同的rowid,但它在前一种情况下是如何工作的(没有and prior rowid = rowid)?

1 个答案:

答案 0 :(得分:2)

如果col包含'val1;val2;val3;val4'之类的内容,就会发生这种情况。然后每个下一个级别仍将匹配同一行,因为您没有使用前一行的任何字段值,而只是级别。

SQL-Fiddle证明了我的建议:http://sqlfiddle.com/#!4/10b11/1/0

Oracle尝试检测循环,但只检查查询中是否使用prior关键字。这个现象也或多或少地在这个页面上描述:http://www.dba-oracle.com/t_advanced_sql_connect_by_loop.htm在“没有先前的连接”标题下:

  

CONNECT BY without PRIOR

     

Vadim记录的分层查询的一种非常流行的用法   Tropashko在他的书“SQL设计模式”中,就是生成行。

SELECT 
   SYS_CONNECT_BY_PATH(DUMMY, '/') 
FROM 
   DUAL 
CONNECT BY 
   LEVEL<4;

SYS_CONNECT_BY_PATH(DUMMY,'/')
--------------------------------
/X
/X/X
/X/X/X
     

注意:根据官方文档,PRIOR是强制性的。   Oracle数据库SQL语言参考(11.1)“在分层结构中   查询,CONNECT BY条件中的一个表达式必须由   PRIOR运营商“。

     

双行的单行既是父亲又是孩子,但是   没有生成循环。这是一种非常有效的生成行的方法。