调用此代码的客户端受到限制,只能处理来自存储过程的返回码.因此,我们将错误时通常的合约修改为RETURN -1,如果没有错误则默认为RETURN 0
如果代码命中内部catch块,则RETURN代码默认为-4而不是0
有谁知道这来自哪里?供参考
干杯
GBN
IF OBJECT_ID('dbo.foo') IS NOT NULL DROP TABLE dbo.foo GO CREATE TABLE dbo.foo ( KeyCol char(12) NOT NULL,ValueCol xml NOT NULL,Comment varchar(1000) NULL,CONSTRAINT PK_foo PRIMARY KEY CLUSTERED (KeyCol) ) GO IF OBJECT_ID('dbo.bar') IS NOT NULL DROP PROCEDURE dbo.bar GO CREATE PROCEDURE dbo.bar @Key char(12),@Value xml,@Comment varchar(1000) AS SET NOCOUNT ON DECLARE @StartTranCount tinyint; BEGIN TRY SELECT @StartTranCount = @@TRANCOUNT; IF @StartTranCount = 0 BEGIN TRAN; BEGIN TRY --SELECT @StartTranCount = 'fish' --generates an error and goes to outer CATCH INSERT dbo.foo (KeyCol,ValueCol,Comment) VALUES (@Key,@Value,@Comment); END TRY BEGIN CATCH IF ERROR_NUMBER() = 2627 --PK violation UPDATE dbo.foo SET ValueCol = @Value,Comment = @Comment WHERE KeyCol = @Key; ELSE RAISERROR ('Tits up',16,1); END CATCH IF @StartTranCount = 0 COMMIT TRAN; END TRY BEGIN CATCH IF @StartTranCount = 0 AND XACT_STATE() <> 0 ROLLBACK TRAN; RETURN -1 END CATCH --Without this,we'll send -4 if we hit the UPDATE CATCH block above --RETURN 0 GO --please run these **separately** --Run with RETURN 0 and fish line commented out DECLARE @rtn int EXEC @rtn = dbo.bar 'abcdefghijkl','<foobar />','testing' SELECT @rtn; SELECT * FROM dbo.foo GO DECLARE @rtn int EXEC @rtn = dbo.bar 'abcdefghijkl','<foobar2 />','testing2' --updated OK but we get @rtn = -4 SELECT @rtn; SELECT * FROM dbo.foo GO --uncomment fish line DECLARE @rtn int EXEC @rtn = dbo.bar 'abcdefghijkl','testing' --Hit outer CATCH,@rtn = -1 as expected SELECT @rtn; SELECT * FROM dbo.foo
解决方法
在玩这个过程时,我可以得到一个返回-6,如果我在foo.KeyCol中插入一个null并删除内部catch中的RAISERROR.这是sql Server正在做的事情,并在此处记录:
Return Values from Stored Procedures.