Em sistemas corporativos, é extremamente comum nos depararmos com dados que possuem uma estrutura de relacionamento hierárquico (parent-child). Exemplos clássicos incluem organogramas empresariais (onde um funcionário se reporta a um gerente, que por sua vez se reporta a um diretor), estruturas de árvore de categorias de produtos, listas de materiais (*Bill of Materials - BOM*) na indústria ou mapas de rotas logísticas.
Consultar essas estruturas utilizando apenas junções comuns (JOIN) pode se tornar um desafio complexo e engessado, especialmente quando a profundidade da árvore de dados é desconhecida ou variável. Para solucionar esse problema com máxima elegância e performance, o banco de dados Oracle disponibiliza as cláusulas nativas START WITH e CONNECT BY.
Uma tabela armazena dados hierárquicos quando possui uma coluna de chave estrangeira que aponta para a chave primária da própria tabela (uma relação reflexiva ou auto-relacionamento). Por exemplo, em uma tabela de employees, podemos ter as colunas:
A estrutura de uma consulta hierárquica no padrão Oracle utiliza operadores direcionais especiais para percorrer os galhos da árvore de dados:
SELECT LEVEL AS nivel_hierarquico, LPAD(' ', 2 * (LEVEL - 1)) || full_name AS organograma_visual, job_title, employee_id, manager_id FROM employees START WITH manager_id IS NULL -- Começa pelo topo (ex: o presidente que não possui chefe) CONNECT BY PRIOR employee_id = manager_id;
O Oracle fornece pseudocolunas e funções embutidas extremamente úteis para enriquecer a navegação em árvores de dados:
SELECT employee_id, full_name, SYS_CONNECT_BY_PATH(full_name, ' -> ') AS caminho_hierarquico FROM employees START WITH manager_id IS NULL CONNECT BY PRIOR employee_id = manager_id;
Em bases de dados legadas ou mal mantidas, inconsistências de dados podem fazer com que um funcionário aponte para si mesmo como gestor ou crie um ciclo fechado (onde o subordinado é chefe do próprio chefe). Quando isso ocorre, uma consulta hierárquica comum falhará com o famoso erro ORA-01436: CONNECT BY loop in user data.
Para proteger sua aplicação contra esse cenário, utilize sempre a cláusula CONNECT BY NOCYCLE combinada com a verificação de segurança:
SELECT employee_id, full_name FROM employees START WITH manager_id IS NULL CONNECT BY NOCYCLE PRIOR employee_id = manager_id;
Dominar consultas hierárquicas com START WITH e CONNECT BY capacita o desenvolvedor a extrair informações complexas de estruturas em árvore de forma limpa, rápida e estruturada diretamente no banco de dados.