sql >> Databasteknik >  >> RDS >> Sqlserver

Outer Apply Returnerar kolumner oväntat INTE NULL när ingen matchning

Detta är verkligen en bugg i produkten.

Ett liknande fel har redan rapporterats och stängts som "Kommer inte att fixa" .

Inklusive denna fråga, det länkade anslutningsobjektet och en annan två frågor på den här webbplatsen Jag har sett fyra fall av denna typ av beteende med inline TVFs och OUTER APPLY - Alla var av formatet

OUTER APPLY dbo.SomeFunction(...) F

Och returnerade korrekta resultat när de skrevs som

OUTER APPLY (SELECT * FROM dbo.SomeFunction(...)) F

Så det här ser ut som en möjlig lösning.

För frågan

WITH Test AS
(
       SELECT 12 AS PropertyID,
              $350000 AS Ap1,
              350000 AS Ap2
)
SELECT LP.*
FROM Test T
OUTER APPLY dbo.TVFTest
(
       T.PropertyID,
       T.Ap1,
       T.Ap2
) LP;

Utförandeplanen ser ut som

Och listan över utdatakolumner i den slutliga projektionen är. Expr1000, Expr1001, Expr1003, Expr1004.

Men bara två av dessa kolumner är definierade i tabellen med konstanter längst ner till höger.

Den bokstavliga $350000 definieras i tabellen över konstanter uppe till höger (Expr1001). Detta blir sedan yttre sammanfogat på tabellen med konstanter längst ner till höger. Eftersom inga rader matchar kopplingsvillkoret utvärderas de två kolumner som definieras där (Expr1003, Expr1004) korrekt som NULL. sedan lägger beräkningsskalären till den bokstavliga 12 in i dataflödet som en ny kolumn (Expr1000) oavsett resultatet av den yttre sammanfogningen.

Detta är inte alls den korrekta semantiken. Jämför med den (rätta) planen när inline TVF är manuellt infogat.

WITH Test
     AS (SELECT 12      AS PropertyID,
                $350000 AS Ap1,
                350000  AS Ap2)
SELECT LP.*
FROM   Test T
       OUTER APPLY (SELECT KeyID,
                           MatchValue1,
                           MatchValue2,
                           CASE
                             WHEN MatchValue1 <> MatchValue2
                               THEN 'Not equal'
                             ELSE 'Something else'
                           END AS MatchTest
                    FROM   (SELECT T.PropertyID AS KeyID,
                                   T.Ap1        AS MatchValue1,
                                   T.Ap2        AS MatchValue2) TestRow
                    WHERE  MatchValue1 <> MatchValue2) LP 

Här är kolumnerna som används i den slutliga projektionen Expr1003, Expr1004, Expr1005, Expr1006 . Alla dessa definieras i den nedre högra konstanta skanningen.

I TVF:s fall verkar allt gå fel väldigt tidigt.

Lägger till OPTION (RECOMPILE, QUERYTRACEON 3604, QUERYTRACEON 8606); visar att inmatningsträdet till processen redan är felaktigt. Uttryckt i SQL är det ungefär.

SELECT Expr1000,
       Expr1001,
       Expr1003,
       Expr1004
FROM   (VALUES (12,
               $350000,
               350000)) V1(Expr1000, Expr1001, Expr1002)
       OUTER APPLY (SELECT Expr1003,
                           IIF(Expr1001 <> Expr1003, 
                               'Not equal', 
                               'Something else') AS Expr1004
                    FROM   (SELECT CAST(Expr1002 AS MONEY) AS Expr1003) D
                    WHERE  Expr1001 <> Expr1003) OA 

Den fullständiga utmatningen av den spårningsflaggan är som följer (Och 8605 visar i princip samma träd.)

*** Input Tree: ***
        LogOp_Project COL: Expr1000  COL: Expr1001  COL: Expr1003  COL: Expr1004 

            LogOp_Apply (x_jtLeftOuter)

                LogOp_Project

                    LogOp_ConstTableGet (1) [empty]

                    AncOp_PrjList 

                        AncOp_PrjEl COL: Expr1000 

                            ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=12)

                        AncOp_PrjEl COL: Expr1001 

                            ScaOp_Const TI(money,ML=8) XVAR(money,Not Owned,Value=(10000units)=(-794967296))

                        AncOp_PrjEl COL: Expr1002 

                            ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=350000)

                LogOp_Project

                    LogOp_Select

                        LogOp_Project

                            LogOp_ConstTableGet (1) [empty]

                            AncOp_PrjList 

                                AncOp_PrjEl COL: Expr1003 

                                    ScaOp_Convert money,Null,ML=8

                                        ScaOp_Identifier COL: Expr1002 

                        ScaOp_Comp x_cmpNe

                            ScaOp_Identifier COL: Expr1001 

                            ScaOp_Identifier COL: Expr1003 

                    AncOp_PrjList 

                        AncOp_PrjEl COL: Expr1004 

                            ScaOp_IIF varchar collate 53256,Var,Trim,ML=14

                                ScaOp_Comp x_cmpNe

                                    ScaOp_Identifier COL: Expr1001 

                                    ScaOp_Identifier COL: Expr1003 

                                ScaOp_Const TI(varchar collate 53256,Var,Trim,ML=9) XVAR(varchar,Owned,Value=Len,Data = (9,Not equal))

                                ScaOp_Const TI(varchar collate 53256,Var,Trim,ML=14) XVAR(varchar,Owned,Value=Len,Data = (14,Something else))

            AncOp_PrjList 

*******************


  1. Hur kan sortering av objekt i hinkar formuleras som ett giltigt JPQL-uttryck?

  2. hur man återställer databaser i phpmyadmin efter avinstallation av xampp

  3. PostgreSQL 9.4 - Använd anpassad operator i EXCLUDE-begränsningen

  4. Oracle får främmande nycklar