如果有人之前遇到过这个问题并且根本原因是什么,那就很好奇。问题是在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
现在设置已完成,让我们运行实际代码,首先是“包括实际执行计划”
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。
现在打开包含实际执行计划,您将收到NULL结果并看到错误(在SQL 2012中):
Msg 50000,Level 16,State 10,Procedure test,Line 33 字符串或二进制数据将被截断。
包含实际执行计划并从proc中删除Try / Catch块会删除错误并返回正确的结果。然而,这在2008R2再次正常。
有什么想法吗?
由于
答案 0 :(得分:2)
我还没有给你答案,只是你可能遇到过错误的更多弹药。
首先,要证明这不涉及RAISERROR
,请将该行更改为:
THROW;
返回此错误消息:
Msg 8152,Level 16,State 10,Procedure test,Line 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在编译和/或生成这个简单批处理的元数据方面存在某种问题。
似乎是一个非常简单的复制品,你有办法,但是I would definitely file this on Connect。
修改强>
我看到你提交了一个错误;任何能够重现这种情况的人都应该投票并确认复制:
http://connect.microsoft.com/SQLServer/feedback/details/785151/show-actual-query-plan-causes-error