4

誰かが以前にこの問題を経験したことがあるかどうか、また根本的な原因が何かに興味があります。問題は、Include Actual Query Plan をオンにして SQL 2012 で実行するとエラーが発生することです。2008 R2 ではどちらの方法でも (プランの有無にかかわらず) 動作し、2012 ではプランを有効にしなくても動作します。パーティション分割されたビューに対して機能をテストしているときに、これを発見しました。

--Setup
USE master
go 

DROP DATABASE Test
GO

CREATE DATABASE Test
GO

USE Test
GO

CREATE TABLE DD (pkID int IDENTITY(1,1), FullDate date);
INSERT INTO DD (FullDate) VALUES ('2013-01-01')
INSERT INTO DD (FullDate) VALUES ('2013-01-02')
INSERT INTO DD (FullDate) VALUES ('2013-01-03')
INSERT INTO DD (FullDate) VALUES ('2013-01-04')
INSERT INTO DD (FullDate) VALUES ('2013-01-05')
GO

CREATE TABLE DC (pkID int IDENTITY(1,1), Filter varchar(32), FilterGroup varchar(32));
INSERT INTO DC (Filter, FilterGroup) VALUES ('one', 'groupone')
INSERT INTO DC (Filter, FilterGroup) VALUES ('two', 'grouptwo')
INSERT INTO DC (Filter, FilterGroup) VALUES ('three', 'groupone')
GO

CREATE TABLE FDA1 (pkID int IDENTITY(1,1), fkpID int, fkCID int, fkDateID int)
INSERT INTO FDA1(fkpID, fkCID, fkDateID) VALUES (1,1,1)
INSERT INTO FDA1(fkpID, fkCID, fkDateID) VALUES (1,2,1)
INSERT INTO FDA1(fkpID, fkCID, fkDateID) VALUES (1,1,3)
INSERT INTO FDA1(fkpID, fkCID, fkDateID) VALUES (1,3,5)
GO

CREATE TABLE FDA2 (pkID int IDENTITY(1,1), fkpID int, fkCID int, fkDateID int)
INSERT INTO FDA2(fkpID, fkCID, fkDateID) VALUES (2,1,2)
INSERT INTO FDA2(fkpID, fkCID, fkDateID) VALUES (2,2,2)
INSERT INTO FDA2(fkpID, fkCID, fkDateID) VALUES (2,1,4)
INSERT INTO FDA2(fkpID, fkCID, fkDateID) VALUES (2,3,5)
GO

CREATE VIEW FDA 
AS
    SELECT pkID, fkpID, fkCID, fkDateID FROM FDA1
    UNION ALL
    SELECT pkID, fkpID, fkCID, fkDateID FROM FDA2
GO

CREATE FUNCTION GetFilter
(
    @pID int
    , @filterGroup varchar(32)
)
RETURNS @Filter TABLE 
(
    CID int
)
AS
BEGIN
    INSERT INTO
        @Filter
    SELECT 
        dc.pkID 
    FROM
        DC dc
    WHERE
        dc.FilterGroup = @filterGroup 
    RETURN
END
GO

CREATE PROC test (@ID int)
AS
BEGIN
    BEGIN TRY
        DECLARE @FilterGroup varchar(32) = 'groupone'

        SELECT
            CAST(MIN(dd.FullDate) As datetime) as ProjectReviewStartDate
        FROM
            dbo.FDA fda
            INNER JOIN dbo.DD dd On fda.fkDateID = dd.pkID 
            INNER JOIN dbo.GetFilter(@ID, @FilterGroup) ctl on fda.fkCID = ctl.CID  
        WHERE
            fda.pkID = @ID 
        OPTION (RECOMPILE);
        RETURN 0;
    END TRY
    BEGIN CATCH

        --Declare variables for error information.
        Declare
            @ErrorMessage nvarchar(max),
            @ErrorSeverity bigint,
            @ErrorState int;

        --Populate error information.
        Select
            @ErrorMessage = ERROR_MESSAGE(),
            @ErrorSeverity = ERROR_SEVERITY(),
            @ErrorState = ERROR_STATE();

        --Re-throw error to calling method.
        RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);

        --Failure
        RETURN -1;
    END CATCH;
END
GO

セットアップが完了したので、実際のコードを実行してみましょう。まず「Include Actual Execution Plan」

USE Test
GO

SET STATISTICS IO ON;
SET STATISTICS TIME ON;
GO

DECLARE @id int = 1
DECLARE @tbl table (dt datetime)
DECLARE @findate datetime

INSERT @tbl EXEC test @id

SELECT @findate = dt FROM @tbl
SELECT @findate
GO

2013-01-01 00:00:00.000 の結果を受け取るはずです。

ここで、Include Actual Execution Plan をオンにすると、結果が NULL になり、エラーが表示されます (SQL 2012 の場合)。

メッセージ 50000、レベル 16、状態 10、手順テスト、行 33 文字列またはバイナリ データは切り捨てられます。

Include Actual Execution Plan をオンにして、Try/Catch ブロックを proc から削除すると、エラーが削除され、正しい結果が返されます。ただし、これは 2008R2 でも問題なく動作します。

何か案は?

ありがとう

4

1 に答える 1

2

バグに遭遇した可能性が高い弾薬が増えただけです。

まず、これが特に関与していないことを証明するために、RAISERRORその行を次のように変更します。

THROW;

代わりに次のエラー メッセージを返します。

メッセージ 8152、レベル 16、状態 10、手順テスト、行 7
文字列またはバイナリ データが切り捨てられます。

したがって、これは、呼び出しでエラーが発生していることを示しており、実際の計画の表示SELECTとの組み合わせに関係があります。TRY/CATCH

次に、メタデータがストアド プロシージャの出力として何を記述しているかを見てみましょう。

SELECT name, system_type_name
  FROM sys.dm_exec_describe_first_result_set_for_object
  (OBJECT_ID('test'), NULL);

結果:

name                    system_type_name
----------------------  ----------------
ProjectReviewStartDate  datetime

実行中のバッチのメタデータをテストしようとすると、メタデータについて何が表示されるかを見てみましょう (実際には、エラー メッセージが表示されます)。

SELECT [error_message]
FROM sys.dm_exec_describe_first_result_set(N'DECLARE @id int = 1
  DECLARE @tbl table (dt datetime)
 DECLARE @findate datetime
 INSERT @tbl 
 EXEC test @id', -1, NULL);

結果:

error_message
----------------------------------------------------------
Incorrect syntax near '-'.
The batch could not be analyzed because of compile errors.

-バッチにはありません。これは実行計画をオフにした状態です。上記のバッチで挿入をコメントアウトしても、同じ結果が得られます。たとえば:

SELECT error_message
  FROM sys.dm_exec_describe_first_result_set(N'EXEC test 1', -1, NULL);

エラーメッセージが少し変わります (よく見てください):

error_message
----------------------------------------------------------
Incorrect syntax near '1'.
The batch could not be analyzed because of compile errors.

showplan または潜在的な切り捨ての関与を取り除きましたが、SQL Server がこの単純なバッチのメタデータをコンパイルおよび/または生成する際に何らかの問題があることを示すことができます。

非常に単純な再現のようで、回避策がありますが、私は間違いなくこれを Connect に提出します

編集

バグを報告したようです。この状況を再現できる他の人は、投票して再現を確認する必要があります。

http://connect.microsoft.com/SQLServer/feedback/details/785151/show-actual-query-plan-causes-error

于 2013-04-19T17:44:04.150 に答える