Megosztás a következőn keresztül:


Beágyazott Common Table Expression (CTE) a Fabric adattárházakban (Transact-SQL)

A következőre vonatkozik:SQL Analytics-végpont és Warehouse a Microsoft Fabricben

A gyakori táblakifejezések (CTE-k) leegyszerűsíthetik az összetett lekérdezéseket, ha az általában összetett lekérdezéseket újrafelhasználható blokkokba bontják.

A CTE-nek négy típusa van: standard, szekvenciális, rekurzívés beágyazott CTE.

  • A standard CTE nem hivatkozik vagy definiál egy másik CTE-t a definíciójában.
  • A beágyazott CTE definíciója magában foglalja egy másik CTE meghatározását is.
  • A szekvenciális CTE definíciója hivatkozhat egy meglévő CTE-ra, de nem definiálhat másik CTE-t.
  • A rekurzív CTE a definíciójában önmagára hivatkozik.

A Microsoft Fabricben a Fabric Data Warehouse és az SQL Analytics-végpont egyaránt támogatja a standard, a szekvenciális és a beágyazott CTE-ket, de a rekurzív CT-ket nem.

A gyakori táblakifejezésekről további információt a WITH common_table_expression (Transact-SQL)című témakörben talál.

Szintaxis

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
    )

Beágyazott CTE létrehozásának és használatának irányelvei

A szabványos CTE-k létrehozásának és használatának irányelvei mellett további irányelveket is talál a beágyazott CTE-khez:

  • Beágyazott CTE csak SELECT utasításban használható. Az UPDATE, INSERT vagy DELETE utasításokban nem használható.
  • Beágyazott CTE definíciójában nem engedélyezett az UPDATE, INSERT vagy DELETE utasítás.
  • Az azonos beágyazási szinten lévő CTE-nevek nem duplikálhatók.
  • A beágyazott CTE csak a beágyazott CTE- vagy szekvenciális CTE-k számára látható, amelyek közvetlenül magasabb szinten vannak.
  • Az adatbázisközi lekérdezések beágyazott CTE-definíciókban engedélyezettek.
  • A lekérdezési tippek (pl. OPTION záradék) nem használhatók beágyazott CTE-definíciókban.
  • A beágyazott CTE nem használható a CREATE NÉZETBEN.
  • Az AS OF nem támogatott a beágyazott CTE definíciójában.
  • A beágyazott CT-k támogatottak egy CTE-alquery-definícióban, de általános alqueryben nem.
  • A legjobb élmény érdekében korlátozza a beágyazási szinteket 64-re.
  • A beágyazott CTE létrehozható a Fabric Query Editorban vagy az SQL Server Management Studióban (SSMS). Az SSMS intellisense nem ismeri fel a beágyazott CTE szintaxist, de ez nem blokkolja a beágyazott CTE létrehozását.

Példák

Különbségek a standard, a szekvenciális és a beágyazott CTE-k között

-- 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;

A CTE névhatóköre a hatókörére korlátozódik

A CTE-nevek különböző beágyazási szinteken használhatók újra. Az azonos beágyazási szinten lévő CTE-nevek nem duplikálhatók. Ebben a példában a cte1 név a külső és a belső hatókörben is használatos.

;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
    )

Összetett beágyazott CTE az unióval, az összes egyesítővel, a metszettel és a kivételével

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;

A beágyazott CTE támogatott a CTE-alquery definíciójában, de általában nem.

Ez a lekérdezés a következő hibával meghiúsul: 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;

A CTE-re mutató hivatkozások nem léphetik túl a hatókörét

Ez a lekérdezés a következő hibával meghiúsul: 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;