2013-11-19 2 views
0

У меня есть иерархический запрос, который возвращает ту же строку (по 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 говорит мне, что у меня есть цикл в моих данных? Это кажется разумным, потому что у меня есть строка с той же самой строкой, что и родитель и ребенок, но как она работала в предыдущем случае (без and prior rowid = rowid)?

+1

Каковы исходные данные, которые вы запрашиваете? –

ответ

2

Похоже, что это может произойти, если col будет содержать что-то вроде 'val1;val2;val3;val4'. Тогда каждый следующий уровень по-прежнему будет соответствовать одной и той же строке, так как вы не используете какое-либо значение поля предыдущей строки, а только уровень.

SQL-Fiddle доказать мое предложение: http://sqlfiddle.com/#!4/10b11/1/0

Oracle пытается обнаружить на велосипеде, но только это проверяет, если prior используется ключевое слово в запросе. Это Fenomenon также более или менее описано на этой странице: http://www.dba-oracle.com/t_advanced_sql_connect_by_loop.htm под заголовком «CONNECT BY без ПРИОР»:

CONNECT BY без ПРЕДВАРИТЕЛЬНОГО

Очень популярное использование иерархического запроса, документально Vadim Tropashko в своей книге SQL Design Patterns, предназначен для создания строк.

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

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

ПРИМЕЧАНИЕ: Согласно официальной документации, ПРИОР является обязательным. Oracle Database SQL Language Reference (11.1) «В иерархическом запросе одно выражение в условии CONNECT BY должно быть квалифицировано оператором ПРИОР».

Единственная строка двойника - это как родительский, так и сам ребенок, но никакой цикл не генерируется. Это очень эффективный способ создания строк.

+0

это нормально, но почему, когда я добавляю другое условие к запросу 'connect by' clause, заявляя, что существует цикл? http://sqlfiddle.com/#!4/10b11/2 –

+0

Да, это связано с использованием ключевого слова 'previous'. Это заставляет Oracle проверять цикличность. Я обновил свой ответ. – GolezTrol

+0

Можно ли использовать 'previous' в' connect by', но обрабатывать циклы по условию в разделе 'connect by'? –

Смежные вопросы