Consultas hierárquicas e recursivas em SQL - Hierarchical and recursive queries in SQL
Uma consulta hierárquica é um tipo de consulta SQL que trata os dados do modelo hierárquico . Eles são casos especiais de consultas recursivas de pontos fixos mais gerais, que calculam fechamentos transitivos .
No SQL: 1999 padrão, as consultas hierárquicas são implementadas por meio de expressões de tabela comuns recursivas (CTEs). Ao contrário da cláusula connect-by anterior da Oracle, os CTEs recursivos foram projetados com semântica de pontos fixos desde o início. CTEs recursivos do padrão eram relativamente próximos da implementação existente no IBM DB2 versão 2. CTEs recursivos também são suportados pelo Microsoft SQL Server (desde SQL Server 2008 R2), Firebird 2.1 , PostgreSQL 8.4+ , SQLite 3.8.3+ , IBM Informix versão 11.50+, CUBRID , MariaDB 10.2+ e MySQL 8.0.1+ . O Tableau tem uma documentação que descreve como os CTEs podem ser usados. O TIBCO Spotfire não oferece suporte a CTEs, enquanto a implementação do Oracle 11g Release 2 carece de semântica de ponto de fixação.
Sem expressões de tabela comuns ou cláusulas conectadas por, é possível realizar consultas hierárquicas com funções recursivas definidas pelo usuário.
Expressão de tabela comum
A expressão de tabela comum, ou CTE, (em SQL ) é um conjunto de resultados nomeado temporário, derivado de uma consulta simples e definidas no âmbito de execução de um SELECT
, INSERT
, UPDATE
, ou DELETE
declaração.
CTEs podem ser considerados como alternativas para tabelas derivadas ( subconsulta ), visualizações e funções definidas pelo usuário em linha.
Expressões de tabela comuns são suportadas por Teradata (começando com a versão 14), DB2 , Informix (começando com a versão 14.1), Firebird (começando com a versão 2.1), Microsoft SQL Server (começando com a versão 2005), Oracle (com recursão desde 11g versão 2 ), PostgreSQL (desde 8.4), MariaDB (desde 10.2), MySQL (desde 8.0), SQLite (desde 3.8.3), HyperSQL , Informix (desde 14.10), Google BigQuery , Sybase (desde a versão 9), Vertica , H2 (experimental) e muitos outros . A Oracle chama os CTEs de "fatoração de subconsulta".
A sintaxe de um CTE (que pode ou não ser recursiva) é a seguinte:
WITH [RECURSIVE] with_query [, ...]
SELECT ...
onde with_query
a sintaxe é:
query_name [ (column_name [,...]) ] AS (SELECT ...)
CTEs recursivos podem ser usados para atravessar relações (como gráficos ou árvores), embora a sintaxe seja muito mais envolvente porque não há pseudocolunas automáticas criadas (como LEVEL
abaixo ); se forem desejados, eles devem ser criados no código. Consulte a documentação do MSDN ou a documentação da IBM para obter exemplos de tutoriais.
A RECURSIVE
palavra-chave geralmente não é necessária após WITH em sistemas diferentes do PostgreSQL.
No SQL: 1999, uma consulta recursiva (CTE) pode aparecer em qualquer lugar em que uma consulta seja permitida. É possível, por exemplo, nomear o resultado usando CREATE
[ RECURSIVE
] VIEW
. Usando um CTE dentro de um INSERT INTO
, pode-se preencher uma tabela com dados gerados a partir de uma consulta recursiva; a geração de dados aleatórios é possível usando esta técnica sem usar quaisquer instruções procedimentais.
Alguns bancos de dados, como PostgreSQL, suportam um formato CREATE RECURSIVE VIEW mais curto que é traduzido internamente para a codificação WITH RECURSIVE.
Um exemplo de consulta recursiva computando o fatorial de números de 0 a 9 é o seguinte:
WITH RECURSIVE temp (n, fact) AS
(SELECT 0, 1 -- Initial Subquery
UNION ALL
SELECT n+1, (n+1)*fact FROM temp -- Recursive Subquery
WHERE n < 9)
SELECT * FROM temp;
CONECTAR POR
Uma sintaxe alternativa é a CONNECT BY
construção não padrão ; foi introduzido pela Oracle na década de 1980. Antes do Oracle 10g, a construção só era útil para percorrer gráficos acíclicos porque retornava um erro ao detectar qualquer ciclo; na versão 10g a Oracle introduziu o recurso NOCYCLE (e palavra-chave), fazendo com que a travessia funcionasse também na presença de ciclos.
CONNECT BY
é compatível com Snowflake , EnterpriseDB , banco de dados Oracle , CUBRID , IBM Informix e DB2, embora apenas se estiver ativado como um modo de compatibilidade. A sintaxe é a seguinte:
SELECT select_list
FROM table_expression
[ WHERE ... ]
[ START WITH start_expression ]
CONNECT BY [NOCYCLE] { PRIOR child_expr = parent_expr | parent_expr = PRIOR child_expr }
[ ORDER SIBLINGS BY column1 [ ASC | DESC ] [, column2 [ ASC | DESC ] ] ... ]
[ GROUP BY ... ]
[ HAVING ... ]
...
- Por exemplo,
SELECT LEVEL, LPAD (' ', 2 * (LEVEL - 1)) || ename "employee", empno, mgr "manager"
FROM emp START WITH mgr IS NULL
CONNECT BY PRIOR empno = mgr;
O resultado da consulta acima seria semelhante a:
level | employee | empno | manager -------+-------------+-------+--------- 1 | KING | 7839 | 2 | JONES | 7566 | 7839 3 | SCOTT | 7788 | 7566 4 | ADAMS | 7876 | 7788 3 | FORD | 7902 | 7566 4 | SMITH | 7369 | 7902 2 | BLAKE | 7698 | 7839 3 | ALLEN | 7499 | 7698 3 | WARD | 7521 | 7698 3 | MARTIN | 7654 | 7698 3 | TURNER | 7844 | 7698 3 | JAMES | 7900 | 7698 2 | CLARK | 7782 | 7839 3 | MILLER | 7934 | 7782 (14 rows)
Pseudo-colunas
- NÍVEL
- CONNECT_BY_ISLEAF
- CONNECT_BY_ISCYCLE
- CONNECT_BY_ROOT
Operadores unários
O exemplo a seguir retorna o sobrenome de cada funcionário no departamento 10, cada gerente acima desse funcionário na hierarquia, o número de níveis entre gerente e funcionário e o caminho entre os dois:
SELECT ename "Employee", CONNECT_BY_ROOT ename "Manager",
LEVEL-1 "Pathlen", SYS_CONNECT_BY_PATH(ename, '/') "Path"
FROM emp
WHERE LEVEL > 1 and deptno = 10
CONNECT BY PRIOR empno = mgr
ORDER BY "Employee", "Manager", "Pathlen", "Path";
Funções
SYS_CONNECT_BY_PATH
Veja também
- Datalog também implementa consultas de fixpoint
- Bancos de dados dedutivos
- Modelo hierárquico
- Acessibilidade
- Fechamento transitivo
- Estrutura de árvore
Referências
Leitura adicional
- Data CJ (2011). SQL e teoria relacional: como escrever código SQL preciso (2ª ed.). O'Reilly Media. pp. 159–163. ISBN 978-1-4493-1640-2.
Livros didáticos acadêmicos . Observe que eles cobrem apenas o padrão SQL: 1999 (e Datalog), mas não a extensão Oracle.
- Abraham Silberschatz; Henry Korth; S. Sudarshan (2010). Conceitos do sistema de banco de dados (6ª ed.). McGraw-Hill. pp. 187–192. ISBN 978-0-07-352332-3.
- Raghu Ramakrishnan; Johannes Gehrke (2003). Sistemas de gerenciamento de banco de dados (3ª ed.). McGraw-Hill. ISBN 978-0-07-246563-1. Capítulo 24.
- Hector Garcia-Molina; Jeffrey D. Ullman; Jennifer Widom (2009). Sistemas de banco de dados: livro completo (2ª ed.). Pearson Prentice Hall. pp. 437–445. ISBN 978-0-13-187325-4.
links externos
- https://stackoverflow.com/questions/1731889/cycle-detection-with-recursive-subquery-factoring
- http://explainextended.com/2009/11/18/sql-server-are-the-recursive-ctes-really-set-based/
- https://web.archive.org/web/20131114094211/http://gennick.com/with.html
- http://www.cs.duke.edu/courses/fall04/cps116/lectures/11-recursion.pdf
- http://www.blacktdn.com.br/2015/06/blacktdn-mssql-usando-consulta-cte.html