To je určitě chyba v produktu.
Podobná chyba byla již nahlášena a uzavřena jako "Neopravím" .
Včetně této otázky, propojené položky připojení a další
dva
otázky na tomto webu Viděl jsem čtyři případy tohoto typu chování s inline TVF a OUTER APPLY
- Všechny byly ve formátu
OUTER APPLY dbo.SomeFunction(...) F
A vrátil správné výsledky, když byl zapsán jako
OUTER APPLY (SELECT * FROM dbo.SomeFunction(...)) F
Takže to vypadá jako možné řešení.
Pro dotaz
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;
Prováděcí plán vypadá takto
A seznam výstupních sloupců v konečné projekci je. Expr1000, Expr1001, Expr1003, Expr1004.
V tabulce konstant vpravo dole jsou však definovány pouze dva z těchto sloupců.
Doslovné $350000
je definována v tabulce konstant vpravo nahoře (Expr1001). To se pak vnější připojí k tabulce konstant vpravo dole. Protože podmínce spojení neodpovídají žádné řádky, dva sloupce zde definované (Expr1003, Expr1004) jsou správně vyhodnoceny jako NULL. pak nakonec výpočetní skalár přidá doslovný 12
do datového toku jako nový sloupec (Expr1000) bez ohledu na výsledek vnějšího spojení.
To není vůbec správná sémantika. Porovnejte se (správným) plánem, když je inline TVF vložen ručně.
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
Zde jsou sloupce použité v konečné projekci Expr1003, Expr1004, Expr1005, Expr1006
. Všechny jsou definovány v konstantním skenování vpravo dole.
V případě TVF se zdá, že se vše pokazí velmi brzy.
Přidávání OPTION (RECOMPILE, QUERYTRACEON 3604, QUERYTRACEON 8606);
ukazuje, že vstupní strom procesu je již nesprávný. Vyjádřeno v SQL je to něco jako.
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
Úplný výstup tohoto příznaku trasování je následující (A 8605 ukazuje v podstatě stejný strom.)
*** 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
*******************