Sql server 显示实际查询计划是否导致错误?

Sql server 显示实际查询计划是否导致错误?,sql-server,tsql,Sql Server,Tsql,好奇以前是否有人遇到过这个问题,以及根本原因是什么。问题在于,在SQL 2012中执行时,如果启用了“包含实际查询计划”,则会发生错误。无论是否有计划,它都能在2008年正常工作,在2012年也能正常工作。我在针对分区视图测试功能时发现了这一点 --Setup USE master go DROP DATABASE Test GO CREATE DATABASE Test GO USE Test GO CREATE TABLE DD (pkID int IDENTITY(1,1), F

好奇以前是否有人遇到过这个问题,以及根本原因是什么。问题在于,在SQL 2012中执行时,如果启用了“包含实际查询计划”,则会发生错误。无论是否有计划,它都能在2008年正常工作,在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
现在安装完成了,让我们运行实际代码,首先“包括实际执行计划”

您应该会收到以下结果:2013-01-01 00:00:00.000

现在启用“包含实际执行计划”,您将收到NULL的结果并看到一个错误(在SQL 2012中):

Msg 50000,16级,状态10,程序测试,第33行 字符串或二进制数据将被截断

启用Include Actual Execution Plan并从进程中删除Try/Catch块时,将删除错误并返回正确的结果。然而,在2008年,这种方法同样适用

有什么想法吗


谢谢

我还没有答案给你,只是你可能遇到了一个bug

首先,为了证明这不涉及
RAISERROR
,具体来说,将该行更改为:

THROW;
返回此错误消息:

Msg 8152,16级,状态10,程序测试,第7行
字符串或二进制数据将被截断

这表明错误发生在
SELECT
调用中,与
TRY/CATCH
和show实际计划的组合有关

接下来,让我们看看元数据将什么描述为存储过程的输出:

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.
批处理中没有
-
。这是在执行计划关闭的情况下。即使在上面的批处理中注释掉了insert,也会得到相同的结果。例如:

SELECT error_message
  FROM sys.dm_exec_describe_first_result_set(N'EXEC test 1', -1, NULL);
错误消息的变化非常轻微(仔细观察):

我们已经消除了showplan的任何参与或潜在的截断,我们仍然可以证明SQL Server在为这个简单的批处理编译和/或生成元数据时存在某种问题

这似乎是一个相当简单的重做,你有变通办法,但

编辑

我看到你已经提交了一个bug;任何其他可以重新编程的人都应投票确认重新编程:

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.