好奇之前是否有人遇到过这个问题以及根本原因是什么。问题是在 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 中):
消息 50000,级别 16,状态 10,过程测试,第 33 行字符串或二进制数据将被截断。
启用包含实际执行计划并从 proc 中删除 Try/Catch 块将删除错误并返回正确的结果。然而,这在 2008R2 中再次运行良好。
有任何想法吗?
谢谢