Dit is zeker een bug in het product.
Een soortgelijke bug is al gemeld en gesloten als "Lost niet op" .
Inclusief deze vraag, het gekoppelde connect-item en een andere
twee
vragen op deze site Ik heb vier gevallen van dit soort gedrag gezien met inline TVF's en OUTER APPLY
- Ze waren allemaal van het formaat
OUTER APPLY dbo.SomeFunction(...) F
En gaf correcte resultaten terug wanneer geschreven als
OUTER APPLY (SELECT * FROM dbo.SomeFunction(...)) F
Dit lijkt dus een mogelijke oplossing.
Voor de vraag
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;
Het uitvoeringsplan ziet eruit als
En de lijst met outputkolommen in de uiteindelijke projectie is. Uitdr1000, Uitdr1001, Uitdr1003, Uitdr1004.
Er zijn echter slechts twee van die kolommen gedefinieerd in de tabel met constanten rechtsonder.
De letterlijke $350000
wordt gedefinieerd in de tabel met constanten in de rechterbovenhoek (Expr1001). Dit wordt dan aan de buitenkant samengevoegd met de tabel met constanten rechtsonder. Aangezien er geen rijen overeenkomen met de join-voorwaarde, worden de twee kolommen die daar zijn gedefinieerd (Expr1003, Expr1004) correct geëvalueerd als NULL. dan voegt de compute scalaire waarde de letterlijke 12
toe in de gegevensstroom als een nieuwe kolom (Expr1000) ongeacht het resultaat van de outer join.
Dit is helemaal niet de juiste semantiek. Vergelijk met het (juiste) plan wanneer de inline TVF handmatig inline is.
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
Hier zijn de kolommen die in de uiteindelijke projectie worden gebruikt Expr1003, Expr1004, Expr1005, Expr1006
. Deze worden allemaal gedefinieerd in de constante scan rechtsonder.
In het geval van de TVF lijkt het al heel vroeg mis te gaan.
OPTION (RECOMPILE, QUERYTRACEON 3604, QUERYTRACEON 8606);
geeft aan dat de invoerboom voor het proces al onjuist is. Uitgedrukt in SQL is het zoiets als.
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
De volledige uitvoer van die traceervlag is als volgt (en 8605 toont in principe dezelfde boom.)
*** 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
*******************