Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Detecção de ciclo com fatoração de subconsulta recursiva


Da documentação em CONNECT_BY_ISCYCLE :

O CONNECT_BY_ISCYCLE pseudocoluna retorna 1 se a linha atual tiver um filho que também seja seu ancestral

e que em CYCLE :

Uma linha é considerada um ciclo se uma de suas linhas ancestrais tiver os mesmos valores para as colunas do ciclo.

No seu exemplo, linha 2 tem um filho que também é seu ancestral, mas seu id ainda não foi devolvido.

Em outras palavras, CONNECT_BY_ISCYCLE verifica os filhos (que ainda não foram retornados), enquanto CYCLE verifica a linha atual (que já foi devolvido).

CONNECT BY é baseado em linhas, enquanto o CTE recursivo s são baseados em conjuntos.

Observe que a documentação da Oracle sobre CYCLE menciona uma "linha ancestral". No entanto, de um modo geral, não há conceito de uma "linha ancestral" em um CTE recursivo . É uma operação baseada em conjunto que pode produzir resultados completamente fora da árvore. De um modo geral, a parte âncora e a parte recursiva podem até usar as diferentes tabelas.

Desde o CTE recursivo s são geralmente usado para construir árvores de hierarquia, Oracle decidiu adicionar uma verificação de ciclo. Mas devido à forma baseada em conjuntos, o CTE recursivo 's operam, geralmente é impossível dizer se a próxima etapa gerará um ciclo ou não, porque sem uma definição clara da condição de ciclo "linha ancestral" também não pode ser definida.

Para realizar o passo "próximo", todo o conjunto "atual" precisa estar disponível, mas para gerar cada linha do conjunto atual (que inclui a coluna do ciclo) precisamos apenas ter os resultados da operação "próximo".

Não é um problema se o conjunto atual sempre consistir em uma única linha (como em CONNECT BY ), mas é um problema se a operação recursiva for definida em um conjunto como um todo.

Não olhou para o Oracle 11 ainda, mas SQL Server implementa CTE recursivo 's apenas ocultando um CONNECT BY atrás deles, o que exige a colocação de inúmeras restrições (todas as quais efetivamente proíbem todas as operações baseadas em conjuntos).

PostgreSQL A implementação de 's, por outro lado, é realmente baseada em conjuntos:você pode fazer qualquer operação com a parte âncora na parte recursiva. Ele não tem nenhum meio para detectar ciclos, no entanto, porque os ciclos não são definidos em primeiro lugar.

Como mencionado anteriormente, MySQL não implementa CTE 's (não implementa HASH JOIN 's ou MERGE JOIN s também, apenas os loops aninhados, então não se surpreenda muito).

Ironicamente, recebi hoje uma carta sobre esse mesmo assunto, que abordarei em meu blog.

Atualização:

CTE recursivo 's em SQL Server não são maiores que CONNECT BY disfarçado. Veja este artigo no meu blog para detalhes chocantes:
  • SQL Server:os CTEs recursivos são realmente baseados em conjuntos?