SQL Server存储过程会引发多个错误

Ban*_*hee 4 .net sql-server stored-procedures exception

我有一个存储过程,我做了一个INSERT然后RAISERROR("MyException", 5, 5)在这种情况下插入失败.

问题是我的.NET应用程序的结果是

MyException:无法插入值NULL ...

所以它在一个中返回2个例外.

我的.NET代码总是将整个字符串与"MyException"匹配,但不再起作用.

这是标准吗?如果是这样,那之前怎么可能有效呢?这有什么设置吗?

编辑:

我使用.NET表适配器来使用SQL数据库.

产品:Microsoft SQL Server Enterprice(64位)版本:11.0.2100.60集群:错误HADR:False

Microsoft Framework .NET 4.6.2

存储过程

ALTER Procedure [dbo].[up_kod_text_save]
            -- Add the parameters for the stored procedure here
            @entity_id int,
    @text varchar(300),
            @kod_key int,

            @kod_id int,
    @korttext varchar(10),
    @inaktiv bit,
    @primar_extern_kod varchar(300),
    @sparad_av varchar(128),
    @kod_typ_id int,
    @kod varchar(20),
    @original_rowver rowversion,
    @associerat_varde decimal(18,5),
    @beskrivning varchar(2000),
    @viktigt_varde bit
AS

BEGIN
            -- SET NOCOUNT ON added to prevent extra result sets from
            -- interfering with SELECT statements.
            SET NOCOUNT ON;
    DECLARE @resultat table(kod_id int,  uppdat_tidpunkt datetime, rowver binary(8) );

            Insert into @resultat 
                         exec up_kod_save @kod_id,@text,@korttext,@inaktiv,@primar_extern_kod,@sparad_av,@kod_typ_id,@kod,@original_rowver, @associerat_varde, @beskrivning,@viktigt_varde

            declare @uppdat_tidpunkt datetime 
            declare @rowver rowversion

            declare @tablename varchar(30)
            declare @idname varchar(30)

            SET @rowver = (SELECT rowver FROM @resultat)
            SET @kod_id = (SELECT kod_id from @resultat)

------------------------------------------------------------------------------------
            set @uppdat_tidpunkt = getdate()

            IF(@kod_key = 2)
            BEGIN
            ELSE IF(@kod_key = 11)
            BEGIN
                         IF  EXISTS ( SELECT akut_checklista_id FROM akut_checklista WHERE akut_checklista_id = @entity_id )
                         BEGIN
                                     UPDATE akut_checklista
                                     SET [text] = @text, 
                                     [kod_id] = @kod_id
                                     WHERE akut_checklista_id = @entity_id
                         END       
                         ELSE
                         BEGIN   
                                     -- Skapa master-rad
                                     INSERT INTO [akut_checklista] ([text], [kod_id])
                                     VALUES (@text, @kod_id);
                                     set @entity_id = SCOPE_IDENTITY()
                         END
            END
            ELSE
            BEGIN
                         RAISERROR ('MyApp_EXCEPTION_UPPDATERAD_AV_ANNAN',16,1)
                         RETURN
            END


            SELECT @entity_id as entity_id, @rowver as rowver, @kod_id as kod_id, @uppdat_tidpunkt as uppdat_tidpunkt
Run Code Online (Sandbox Code Playgroud)

up_kod_save只更新\插入而没有任何事务.但是如果rowversion错误,它可能会失败.

Dan*_*man 10

批处理执行期间发生的严重性为11或更高的错误SqlException将在SqlClientAPI 引发异常时返回给应用程序.在SqlException.Errors集合中返回单个错误,其中SqlException.Message包含集合的各个错误的连接文本.

某些SQL Server错误将终止批处理,因此错误后不会执行批处理中的后续语句.在这种情况下,仅返回批处理终止错误之前发生的错误.发生多个错误且没有批处理终止时,将返回所有错误.因此,根据特定错误,RAISERROR可能不会执行后续操作.

请记住,默认行为是SQL Server将继续在内部和外部过程中执行T-SQL语句,不会发生批处理终止错误,包括RAISERROR严重性为16.这可能导致返回多个错误.

通常,人们不希望在错误之后继续批量执行并引发单个错误.这可以通过以下一种或多种技术来避免:

  • 使用结构化错误处理(TRY/CATCH)并使用THROW而不是RAISERROR

  • 在每个语句之后检查@@ ERROR以及控制流语句

  • 指定SET XACT_ABORT_ON,以便将非批处理终止错误提升为批处理终止错误,并回滚事务

SET XACT_ABORT_ON是具有明确事务的存储过程中的最佳实践,以确保在客户端超时或查询取消时回滚事务.除非TRY/CATCH块在范围内,否则批处理也将被终止.

在你的情况下,我建议你在外部proc中添加一个TRY/CATCH块.该CATCH块将在内部或外部proc中发生错误后执行.然后,CATCH块代码可以使用THROW(SQL Server 2012及更高版本)或RAISERROR严重性为11+ 的用户定义错误引发原始错误,以在客户端应用程序中引发异常.以下是一个例子.

CREATE PROCEDURE [dbo].[up_kod_text_save]
    -- parameters here
AS
SET NOCOUNT ON;
BEGIN TRY
    -- code here
END TRY
BEGIN CATCH --catch block will be entered after an error in either proc
    IF @@TRANCOUNT > 0 ROLLBACK; --needed only if BEGIN TRAN is used
    THROW; --this will raise the original error
END;
GO
Run Code Online (Sandbox Code Playgroud)