誰かが以前にこの問題を経験したことがあるかどうか、また根本的な原因が何かに興味があります。問題は、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 でも問題なく動作します。
何か案は?
ありがとう