Geschachtelter Common Table Expression (CTE) in Fabric Data Warehouse (Transact-SQL)
Gilt für: SQL-Analyseendpunkt und Warehouse in Microsoft Fabric
Common Table Expressions (CTEs) kann komplexe Abfragen vereinfachen, indem komplexe Abfragen in wiederverwendbare Blöcke decodiert werden.
Es gibt vier Arten von CTE, einschließlich Standard, sequenzieller, rekursiver und geschachtelter CTE.
- Ein Standard-CTE verweist nicht auf ein anderes CTE oder definiert es in seiner Definition.
- Die Definition einer geschachtelten CTE umfasst das Definieren eines anderen CTE.
- Eine sequenzielle CTE-Definition kann auf eine vorhandene CTE verweisen, aber keine andere CTE definieren.
- Ein rekursives CTE verweist in seiner Definition auf sich selbst.
Fabric Warehouse- und SQL-Analyseendpunkt unterstützen standard-, sequenzielle und geschachtelte CTEs (Vorschau). Standard- und sequenzielle CTEs sind zwar allgemein in Microsoft Fabric verfügbar, geschachtelte CTEs sind derzeit jedoch eine Vorschaufunktion.
Weitere Informationen zu allgemeinen Tabellenausdrücken finden Sie unter WITH common_table_expression (Transact-SQL).For more information about common table expressions, see WITH common_table_expression (Transact-SQL).
Hinweis
Während der Vorschau wird die Erstellung geschachtelter CTE nur von SQL Server Management Studio (SSMS) unterstützt. IntelliSense in SSMS erkennt keine geschachtelte CTE-Syntax, blockiert jedoch nicht das Erstellen von geschachtelten CTE. Um optimale Benutzererfahrung zu erzielen, beschränken Sie die Schachtelungsebenen auf 64.
Syntax
WITH <NESTED_CTE_NAME_LEVEL1> [ (column_name , ...) ] AS
(WITH <NESTED_CTE_NAME_LEVEL2> [ (column_name , ...) ] AS
(
...
WITH <NESTED_CTE_NAME_LEVELn-1> [ ( column_name , ...) ] AS
(
WITH <NESTED_CTE_NAME_LEVELn> [ ( column_name , ...) ] AS
(
Standard_CTE_query_definition
)
<SELECT statement> -- Data source must include NESTED_CTE_NAME_LEVELn
)
<SELECT statement> -- Data source must include NESTED_CTE_NAME_LEVELn-1
...
)
<SELECT statement> -- Data source must include NESTED_CTE_NAME_LEVEL2
)
Richtlinien zum Erstellen und Verwenden eines geschachtelten CTE
Zusätzlich zu Richtlinien für das Erstellen und Verwenden von Standard-CTEs sind hier zusätzliche Richtlinien für geschachtelte CTEs aufgeführt:
- Eine geschachtelte CTE kann nur in einer SELECT-Anweisung verwendet werden. Sie kann nicht in UPDATE-, INSERT- oder DELETE-Anweisungen verwendet werden.
- In der Definition einer geschachtelten CTE sind keine UPDATE-, INSERT- oder DELETE-Anweisungen zulässig.
- CTE-Namen auf derselben Schachtelungsebene können nicht dupliziert werden.
- Eine geschachtelte CTE ist nur für die geschachtelten CTE oder sequenziellen CTEs sichtbar, die sich auf der unmittelbar höheren Ebene befinden.
- Datenbankübergreifende Abfragen sind in einer geschachtelten CTE-Definition zulässig.
- Abfragehinweise (d. h. OPTION-Klausel) sind in einer geschachtelten CTE-Definition nicht zulässig.
- Geschachtelte CTE können in CREATE VIEW nicht verwendet werden.
- AS OF wird in der Definition eines geschachtelten CTE nicht unterstützt.
- Geschachtelte CTEs werden in einer CTE-Unterabfragedefinition unterstützt, aber nicht in einer allgemeinen Unterabfrage.
Beispiele
Unterschiede zwischen Standard-, Sequenz- und geschachtelten CTEs
-- Standard CTE
;WITH Standard_CTE AS (
SELECT * FROM T1
)
SELECT * FROM Standard_CTE;
-- Sequential CTE
;WITH CTE1 AS (
SELECT * FROM T1
),
CTE2 AS (SELECT * FROM CTE1),
CTE3 AS (SELECT * FROM CTE2)
SELECT * FROM CTE3
-- Nested CTE
;WITH OUTER_CTE AS (
WITH INNER_CTE AS (
SELECT * FROM T1
)
SELECT * FROM INNER_CTE
)
SELECT * FROM OUTER_CTE;
Name scope of CTE is restricted to its scope
CTE-Namen können auf verschiedenen Schachtelungsebenen wiederverwendet werden. CTE-Namen auf derselben Schachtelungsebene können nicht dupliziert werden. In diesem Beispiel wird der Name cte1
sowohl im äußeren als auch im inneren Bereich verwendet.
;WITH
cte1 AS (
WITH
inner_cte1_1 AS (
SELECT * FROM NestedCTE_t1 WHERE c1 = 1
),
inner_cte1_2 AS (
SELECT * FROM inner_cte1_1 WHERE c2 = 1
)
SELECT * FROM inner_cte1_2
),
cte2 AS (
WITH
cte1 AS (
SELECT * FROM NestedCTE_t1 WHERE c3 = 1
),
inner_cte2_2 AS (
SELECT * FROM cte1 WHERE c4 = 1
)
SELECT * FROM inner_cte2_2
)
Komplexe geschachtelte CTE mit Union, Union alle, Schneiden und außer
CREATE TABLE NestedCTE_t1 (
c1 INT,
c2 INT,
c3 INT
);
GO
INSERT INTO NestedCTE_t1
VALUES (1, 1, 1);
INSERT INTO NestedCTE_t1
VALUES (2, 2, 2);
INSERT INTO NestedCTE_t1
VALUES (3, 3, 3);
GO
WITH
outermost_cte_1 AS (
WITH
outer_cte_1 AS (
WITH
inner_cte1_1 AS (
SELECT * FROM NestedCTE_t1 WHERE c1 = 1
),
inner_cte1_2 AS (
SELECT * FROM inner_cte1_1
UNION SELECT * FROM inner_cte1_1
)
SELECT * FROM inner_cte1_1
UNION ALL SELECT * FROM inner_cte1_2
),
outer_cte_2 AS (
WITH
inner_cte2_1 AS (
SELECT * FROM NestedCTE_t1 WHERE c2 = 1
EXCEPT SELECT * FROM outer_cte_1
),
inner_cte2_2 AS (
SELECT * FROM NestedCTE_t1 WHERE c3 = 1
UNION SELECT * FROM inner_cte2_1
)
SELECT * FROM inner_cte2_1
UNION ALL SELECT * FROM outer_cte_1
)
SELECT * FROM outer_cte_1
INTERSECT SELECT * FROM outer_cte_2
),
outermost_cte_2 AS (
SELECT * FROM outermost_cte_1
UNION SELECT * FROM outermost_cte_1
)
SELECT * FROM outermost_cte_1
UNION ALL SELECT * FROM outermost_cte_2;
Geschachtelte CTE wird in der CTE-Unterabfragedefinition unterstützt, aber nicht in allgemeiner Unterabfrage
Diese Abfrage schlägt mit dem folgenden Fehler fehl: Msg 156, Level 15, State 1, Line 3. Incorrect syntax near the keyword 'WITH'.
SELECT * FROM
(
WITH
inner_cte1_1 AS (SELECT * FROM NestedCTE_t1 WHERE c1 = 1),
inner_cte1_2 AS (SELECT * FROM inner_cte1_1)
SELECT * FROM inner_cte1_2
) AS subq1;
Verweise auf eine CTE dürfen ihren Bereich nicht überschreiten.
Diese Abfrage schlägt mit dem folgenden Fehler fehl: Msg 208, Level 16, State 1, Line 1. Invalid object name 'inner_cte1_1'.
;WITH
outer_cte_1 AS (
WITH
inner_cte1_1 AS (
SELECT * FROM NestedCTE_t1 WHERE c1 = 1
),
inner_cte1_2 AS (
SELECT * FROM inner_cte1_1 WHERE c2 = 1
)
SELECT * FROM inner_cte1_2
),
outer_cte_2 AS (
WITH inner_cte2_1 AS (
SELECT * FROM NestedCTE_t1 WHERE c3 = 1
)
SELECT
tmp2.*
FROM
inner_cte1_1 AS tmp1,
inner_cte2_1 AS tmp2
WHERE
tmp1.c4 = tmp2.c4
)
SELECT * FROM outer_cte_2;