sql >> データベース >  >> RDS >> Sqlserver

Outer Apply 一致しない場合に予期せず NOT NULL 列を返す

    これは間違いなく製品のバグです。

    同様のバグ が既に報告され、次のようにクローズされました。 「直らない」 .

    この質問、リンクされた接続項目、および 別の 2 このサイトに関する質問 インライン TVF と OUTER APPLY を使用して、このタイプの動作の 4 つのケースを見てきました。 - それらはすべて

    の形式でした
    OUTER APPLY dbo.SomeFunction(...) F
    

    と書くと正しい結果が返ってきました
    OUTER APPLY (SELECT * FROM dbo.SomeFunction(...)) F
    

    したがって、これは可能な回避策のようです。

    クエリについて

    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;
    

    実行計画は次のようになります

    そして、最終的な射影の出力列のリストは次のとおりです。 Expr1000、Expr1001、Expr1003、Expr1004.

    ただし、これらの列のうち、右下の定数のテーブルで定義されているのは 2 つだけです。

    リテラル $350000 右上の定数の表に定義されています (Expr1001)。これは、右下の定数テーブルに外部結合されます。結合条件に一致する行がないため、そこで定義されている 2 つの列 (Expr1003、Expr1004) は正しく NULL として評価されます。最後に、計算スカラーはリテラル 12 を追加します 外部結合の結果に関係なく、新しい列 (Expr1000) としてデータ フローに挿入されます。

    これらはまったく正しいセマンティクスではありません。インライン TVF を手動でインライン化した場合の (正しい) プランと比較してください。

    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 
    

    ここで、最終的な射影で使用される列は Expr1003, Expr1004, Expr1005, Expr1006 です。 .これらはすべて、右下の定数スキャンで定義されています。

    TVF の場合、非常に早い段階ですべてがうまくいかないようです。

    OPTION (RECOMPILE, QUERYTRACEON 3604, QUERYTRACEON 8606); の追加 プロセスへの入力ツリーが既に正しくないことを示しています。 SQL で表現すると、次のようになります。

    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 
    

    そのトレース フラグの完全な出力は次のとおりです (8605 は基本的に同じツリーを示しています)。

    *** 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. phpMyAdminを使用してデータベースを複製する方法

    2. Postgresでロックを保持しているクエリを検出するにはどうすればよいですか?

    3. grailstomcatjndiに最適なmysqlデータソースプロパティ

    4. Oracleの明示カーソルと暗黙カーソルの違いは何ですか?