Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wann sollte EXCEPT im Gegensatz zu NOT EXISTS in Transact SQL verwendet werden?

EXCEPT behandelt NULL Werte als übereinstimmend.

Diese Abfrage:

WITH    q (value) AS
        (
        SELECT  NULL
        UNION ALL
        SELECT  1
        ),
        p (value) AS
        (
        SELECT  NULL
        UNION ALL
        SELECT  2
        )
SELECT  *
FROM    q
WHERE   value NOT IN
        (
        SELECT  value
        FROM    p
        )

gibt ein leeres Rowset zurück.

Diese Abfrage:

WITH    q (value) AS
        (
        SELECT  NULL
        UNION ALL
        SELECT  1
        ),
        p (value) AS
        (
        SELECT  NULL
        UNION ALL
        SELECT  2
        )
SELECT  *
FROM    q
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    p
        WHERE   p.value = q.value
        )

wird zurückkehren

NULL
1

, und diese hier:

WITH    q (value) AS
        (
        SELECT  NULL
        UNION ALL
        SELECT  1
        ),
        p (value) AS
        (
        SELECT  NULL
        UNION ALL
        SELECT  2
        )
SELECT  *
FROM    q
EXCEPT
SELECT  *
FROM    p

gibt zurück:

1

Rekursive Verweise sind auch in EXCEPT erlaubt -Klausel in einem rekursiven CTE , obwohl es sich auf seltsame Weise verhält:Es gibt alles außer der letzten Zeile zurück eines vorherigen Satzes, nicht alles außer dem gesamten vorherigen Satz:

WITH    q (value) AS
        (
        SELECT  1
        UNION ALL
        SELECT  2
        UNION ALL
        SELECT  3
        ),
        rec (value) AS
        (
        SELECT  value
        FROM    q
        UNION ALL
        SELECT  *
        FROM    (
                SELECT  value
                FROM    q
                EXCEPT
                SELECT  value
                FROM    rec
                ) q2
        )
SELECT  TOP 10 *
FROM    rec

---
1
2
3
-- original set
1
2
-- everything except the last row of the previous set, that is 3
1
3
-- everything except the last row of the previous set, that is 2
1
2
-- everything except the last row of the previous set, that is 3, etc.
1

SQL Server Entwickler müssen nur vergessen haben, es zu verbieten.