Oracle
 sql >> база данни >  >> RDS >> Oracle

Откриване на цикъл с рекурсивно факториране на подзаявка

От документацията за CONNECT_BY_ISCYCLE :

CONNECT_BY_ISCYCLE псевдоколона връща 1 ако текущият ред има дете, което е и негов предшественик

и това на CYCLE :

Счита се, че ред образува цикъл, ако един от неговите предшествещи редове има същите стойности за колоните на цикъла.

Във вашия пример, ред 2 има дете, което също е негов предшественик, но неговият id все още не е върнат.

С други думи, CONNECT_BY_ISCYCLE проверявадецата (които тепърва ще бъдат върнати), докато CYCLE проверява текущия ред (което вече е върнато).

CONNECT BY е базиран на ред, докато рекурсивният CTE 's са базирани на набори.

Имайте предвид, че документацията на Oracle за CYCLE споменава "ред с предшественици". Въпреки това, най-общо казано, няма концепция за "ред-предшественик" в рекурсивния CTE . Това е операция, базирана на набор, която може да даде резултати напълно извън дървото. Най-общо казано, анкерната част и рекурсивната част могат дори да използват различните таблици.

Тъй като рекурсивният CTE 's са обикновено използва се за изграждане на йерархични дървета, Oracle реши да добави проверка на цикъла. Но поради базирания на множество начин рекурсивният CTE 's operation, обикновено е невъзможно да се каже дали следващата стъпка ще генерира цикъл или не, тъй като без ясно определение на цикъла „ред-предшественик“ също не може да се дефинира условието на цикъла.

За да изпълним „следващата“ стъпка, целият „текущ“ набор трябва да е наличен, но за да генерираме всеки ред от текущия набор (който включва колоната на цикъла), просто трябва да имаме резултатите от операцията „следваща“.

Не е проблем, ако текущият набор винаги се състои от един ред (като в CONNECT BY ), но е проблем, ако рекурсивната операция е дефинирана върху множество като цяло.

Не разгледах Oracle 11 все още, но SQL Server прилага рекурсивен CTE е като просто скриете CONNECT BY зад тях, което изисква поставянето на множество ограничения (всички от които на практика забраняват всички операции, базирани на набори).

PostgreSQL Реализацията на 's, от друга страна, е наистина базирана на набори:можете да извършвате всяка операция с анкерната част в рекурсивната част. Той обаче няма никакви средства за откриване на цикли, тъй като циклите не са дефинирани на първо място.

Както беше споменато по-горе, MySQL не прилага CTE 's изобщо (не прилага HASH JOIN 's или MERGE JOIN както и само вложените цикли, така че не се изненадвайте много).

По ирония на съдбата днес получих писмо точно по тази тема, която ще разгледам в моя блог.

Актуализация:

Рекурсивен CTE е в SQL Server са не повече от CONNECT BY под прикритие. Вижте тази статия в моя блог за шокиращи подробности:

  • SQL сървър:рекурсивните CTE наистина ли са базирани на множество?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Определяне на датите на Великден за всяка година в Oracle PLSQL

  2. Функция TO_CHAR(число) в Oracle

  3. N-та максимална заплата в Oracle

  4. Как да добавите коментари към таблица в Oracle SQL Developer?

  5. Не е валиден месец при вмъкване на данни в oracle