Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如果远程存储过程失败,则返回_Sql Server_Sql Server 2008_Stored Procedures_Remote Server - Fatal编程技术网

Sql server 如果远程存储过程失败,则返回

Sql server 如果远程存储过程失败,则返回,sql-server,sql-server-2008,stored-procedures,remote-server,Sql Server,Sql Server 2008,Stored Procedures,Remote Server,我正在创建一个存储过程。此存储过程运行本地存储过程和外部存储过程。为简单起见,我将调用本地服务器[local]和远程服务器[remote] 下面是一个简单的拓扑: 程序 在远程过程上使用事务时,会引发以下错误: OLE DB提供程序。。。返回消息合作伙伴事务管理器已禁用对远程/网络事务的支持 我发现我无法在本地为远程过程运行事务 如果此过程的任何部分失败,如何确保此过程将退出并回滚 注释 关于合并简单程序,其中一些单独使用。 您可以尝试将这两个存储过程执行到单独的try-CATCH块中,并检查C

我正在创建一个存储过程。此存储过程运行本地存储过程和外部存储过程。为简单起见,我将调用本地服务器[local]和远程服务器[remote]

下面是一个简单的拓扑:

程序

在远程过程上使用事务时,会引发以下错误:

OLE DB提供程序。。。返回消息合作伙伴事务管理器已禁用对远程/网络事务的支持

我发现我无法在本地为远程过程运行事务

如果此过程的任何部分失败,如何确保此过程将退出并回滚

注释

关于合并简单程序,其中一些单独使用。
您可以尝试将这两个存储过程执行到单独的try-CATCH块中,并检查CATCH块中对应的错误号。若错误号和您得到的错误号相同,您只需根据您的要求返回或提出错误


它是否会导致致命错误。请检查异常情况。

您可以尝试将这两个存储过程执行到单独的try-CATCH块中,并检查CATCH块中对应的错误号。若错误号和您得到的错误号相同,您只需根据您的要求返回或提出错误


它是否会导致致命错误。请检查例外情况。

我可能不太清楚您想要什么。如果需要整个monthlyRollUp SP在远程或本地过程发生故障时回滚,则需要分布式事务协调器。这将允许服务器传递有关事务的信息并协调提交。也就是说,两台服务器都必须指示获得了所有必要的锁,然后协调两台服务器上的提交,以便操作是自动的。以下是设置DTC的一个示例:

如果不希望远程过程参与/影响事务,可以尝试设置:

SET REMOTE_PROC_TRANSACTIONS OFF;

我以前没有使用过这种设置,所以我不确定它是否能满足您的需要。

我可能不太清楚您想要什么。如果需要整个monthlyRollUp SP在远程或本地过程发生故障时回滚,则需要分布式事务协调器。这将允许服务器传递有关事务的信息并协调提交。也就是说,两台服务器都必须指示获得了所有必要的锁,然后协调两台服务器上的提交,以便操作是自动的。以下是设置DTC的一个示例:

如果不希望远程过程参与/影响事务,可以尝试设置:

SET REMOTE_PROC_TRANSACTIONS OFF;
我以前没有使用过这个设置,所以我不确定它是否能满足您的需要。

我最简单的方法是

将返回值添加到远程进程。 将远程进程包装到事务中,并尝试在远程进程内捕获。如果发生错误,则返回false。 在本地存储过程上,如果为false,则不继续。 我也无法理解本地进程中多个BEGIN TRANS/COMMIT背后的原因。我的意思是,如果这是月末汇总,这不是一笔大交易,而不是一堆小交易吗?否则,trans1和trans2可能会成功提交,但3将失败,仅此而已

姓名由ofc组成:

 CREATE PROC [remote].db.REMOTE_PROC ( 
      @return_value int output
 ) 
 AS 
 BEGIN 
      SET XACT_ABORT ON; 
      BEGIN TRY      
           BEGIN TRANS 
           ... do stuff ... 

                set @return_value = 1;
           COMMIT; 
      END TRY 
      BEGIN CATCH 
           set @return_value = 0; 
      END CATCH
 END 
和本地程序

 CREATE PROC [local].db.[monthlyRollUp] AS
 BEGIN 
      SET XACT_ABORT ON; 

      declare @ret int; 

      EXECUTE [remote].dbo.REMOTE_PROC @return_value = @ret OUTPUT; 

      IF @ret = 0 
           PRINT 'ERROR :(' 
           RETURN
      END IF 

      BEGIN TRANS 
           -- one big transaction here 
           EXEC [LOCAL].[DB].[table].[sp1]; 

           EXEC [LOCAL].[DB].[table].[sp2]; 

           EXEC [LOCAL].[DB].[table].[sp3]; 

           EXEC [LOCAL].[DB].[table].[sp4]; 

      COMMIT; 

 END; 
afair[remote].dbo.remote_PROC运行自己的事务空间,如果成功,则返回1。本地进程,检查返回值并决定是否继续

sp1、sp2、sp3和sp4都在一个事务中运行,因为每个事务都有多个事务对我来说没有多大意义

我认为最简单的方法是

将返回值添加到远程进程。 将远程进程包装到事务中,并尝试在远程进程内捕获。如果发生错误,则返回false。 在本地存储过程上,如果为false,则不继续。 我也无法理解本地进程中多个BEGIN TRANS/COMMIT背后的原因。我的意思是,如果这是月末汇总,这不是一笔大交易,而不是一堆小交易吗?否则,trans1和trans2可能会成功提交,但3将失败,仅此而已

姓名由ofc组成:

 CREATE PROC [remote].db.REMOTE_PROC ( 
      @return_value int output
 ) 
 AS 
 BEGIN 
      SET XACT_ABORT ON; 
      BEGIN TRY      
           BEGIN TRANS 
           ... do stuff ... 

                set @return_value = 1;
           COMMIT; 
      END TRY 
      BEGIN CATCH 
           set @return_value = 0; 
      END CATCH
 END 
和本地程序

 CREATE PROC [local].db.[monthlyRollUp] AS
 BEGIN 
      SET XACT_ABORT ON; 

      declare @ret int; 

      EXECUTE [remote].dbo.REMOTE_PROC @return_value = @ret OUTPUT; 

      IF @ret = 0 
           PRINT 'ERROR :(' 
           RETURN
      END IF 

      BEGIN TRANS 
           -- one big transaction here 
           EXEC [LOCAL].[DB].[table].[sp1]; 

           EXEC [LOCAL].[DB].[table].[sp2]; 

           EXEC [LOCAL].[DB].[table].[sp3]; 

           EXEC [LOCAL].[DB].[table].[sp4]; 

      COMMIT; 

 END; 
afair[remote].dbo.remote_PROC运行自己的事务空间,如果成功,则返回1。本地进程,检查返回值并决定是否继续


sp1、sp2、sp3和sp4都在一个事务中运行,因为每个事务都有多个事务对我来说没有多大意义

如果您不能或不想使用DTC,并且不想使用CLR,则需要最后调用远程sp,因为您将无法回滚远程sp调用

SET NOCOUNT, XACT_ABORT ON
SET REMOTE_PROC_TRANSACTIONS OFF;
BEGIN TRY
    DECLARE @ret INT
    BEGIN TRAN
        --Perform these in a transaction, so they all rollback together
        EXEC [LOCAL].[DB].[table].[sp1]
        EXEC [LOCAL].[DB].[table].[sp2]
        EXEC [LOCAL].[DB].[table].[sp3]
        EXEC [LOCAL].[DB].[table].[sp4]
    --We call remote sp last so that if it fails we rollback the above transactions
    --We'll have to assume that remote sp takes care of itself on error.
    EXEC [REMOTE].[DB].[table].[sp] 

    COMMIT
END TRY
BEGIN CATCH
    --We rollback
    ROLLBACK       
    -- Insert error into log table
    INSERT INTO [dbo].[log_table] (stamp, errorNumber, 
        errorSeverity, errorState, errorProcedure, errorLine, errorMessage)
    SELECT GETDATE(), ERROR_NUMBER(), ERROR_SEVERITY(), ERROR_STATE(),ERROR_PROCEDURE(),
    ERROR_LINE(), ERROR_MESSAGE()

END CATCH
如果本地sp依赖于远程存储过程的结果,则可以使用CLR sp将需要外部访问权限并显式管理事务(基本上是一个滚动自己的DTC),但不需要两阶段提交。您实际上是在延迟远程提交

//这不是真正的两阶段提交,但是 //可能足以满足您的需要。边缘情况是,如果出现错误 //尝试提交远程事务时,无法回滚本地事务。 usingSqlConnection cnRemote=新建SqlConnection { 试一试{ cnRemote.Open; //启动远程事务并调用远程存储过程 SqlTransaction trnRemote=cnRemote.BeginTransaction远程传输; SqlCommand cmdRemote=cnRemote.CreateCommand; cmdRemote.Connection=cnRemote; cmdRemote.Transaction=trnRemote; cmdRemote.CommandType=CommandType.StoredProcess; cmdRemote.CommandText='[dbo].[sp1]'; cmdRemote.ExecuteNonQuery; usingSqlConnection cnLocal=new SqlConnectioncontext connection=true { cnLocal.Open; SqlTransaction trnLocal=cnLocal.BeginTransactionLocalTran; SqlCommand cmdLocal=cnLocal.CreateCommand; cmdLocal.Connection=cnLocal; cmdLocal.Transaction=trnLocal; cmdLocal.CommandType=CommandType.StoredProcess; cmdLocal.CommandText='[dbo].[sp1]'; cmdLocal.ExecuteNonQuery; cmdLocal.CommandText='[dbo].[sp2]'; cmdLocal.ExecuteNonQuery; cmdLocal.CommandText='[dbo].[sp3]'; cmdLocal.ExecuteNonQuery; cmdLocal.CommandText='[dbo].[sp4]'; cmdLocal.ExecuteNonQuery; //提交本地事务 trnLocal.Commit; } //提交远程传输 trnRemote.Commit; }//试试看 捕获异常 { //清理工作在这里进行。如果需要,回滚远程传输,记录错误,等等。 } }
如果您不能或不想使用DTC,并且不想使用CLR,则需要最后调用远程sp,因为您将无法回滚远程sp调用

SET NOCOUNT, XACT_ABORT ON
SET REMOTE_PROC_TRANSACTIONS OFF;
BEGIN TRY
    DECLARE @ret INT
    BEGIN TRAN
        --Perform these in a transaction, so they all rollback together
        EXEC [LOCAL].[DB].[table].[sp1]
        EXEC [LOCAL].[DB].[table].[sp2]
        EXEC [LOCAL].[DB].[table].[sp3]
        EXEC [LOCAL].[DB].[table].[sp4]
    --We call remote sp last so that if it fails we rollback the above transactions
    --We'll have to assume that remote sp takes care of itself on error.
    EXEC [REMOTE].[DB].[table].[sp] 

    COMMIT
END TRY
BEGIN CATCH
    --We rollback
    ROLLBACK       
    -- Insert error into log table
    INSERT INTO [dbo].[log_table] (stamp, errorNumber, 
        errorSeverity, errorState, errorProcedure, errorLine, errorMessage)
    SELECT GETDATE(), ERROR_NUMBER(), ERROR_SEVERITY(), ERROR_STATE(),ERROR_PROCEDURE(),
    ERROR_LINE(), ERROR_MESSAGE()

END CATCH
如果本地sp依赖于远程存储过程的结果,那么您可以使用CLR sp,因为它需要外部访问权限并显式管理事务(基本上是您自己的DTC,但不需要两阶段提交)。您实际上是在延迟远程提交

//这不是真正的两阶段提交,但是 //可能足以满足您的需要。边缘情况是,如果出现错误 //尝试提交远程事务时,无法回滚本地事务。 usingSqlConnection cnRemote=新建SqlConnection { 试一试{ cnRemote.Open; //启动远程事务并调用远程存储过程 SqlTransaction trnRemote=cnRemote.BeginTransaction远程传输; SqlCommand cmdRemote=cnRemote.CreateCommand; cmdRemote.Connection=cnRemote; cmdRemote.Transaction=trnRemote; cmdRemote.CommandType=CommandType.StoredProcess; cmdRemote.CommandText='[dbo].[sp1]'; cmdRemote.ExecuteNonQuery; usingSqlConnection cnLocal=new SqlConnectioncontext connection=true { cnLocal.Open; SqlTransaction trnLocal=cnLocal.BeginTransactionLocalTran; SqlCommand cmdLocal=cnLocal.CreateCommand; cmdLocal.Connection=cnLocal; cmdLocal.Transaction=trnLocal; cmdLocal.CommandType=CommandType.StoredProcess; cmdLocal.CommandText='[dbo].[sp1]'; cmdLocal.ExecuteNonQuery; cmdLocal.CommandText='[dbo].[sp2]'; cmdLocal.ExecuteNonQuery; cmdLocal.CommandText='[dbo].[sp3]'; cmdLocal.ExecuteNonQuery; cmdLocal.CommandText='[dbo].[sp4]'; cmdLocal.ExecuteNonQuery; //提交本地事务 trnLocal.Commit; } //提交远程传输 trnRemote.Commit; }//试试看 捕获异常 { //清理工作在这里进行。如果需要,回滚远程传输,记录错误,等等。 } }
是否建议对第一个sp执行TRY…CATCH,检查错误号,然后执行第二个未嵌套的TRY…CATCH?是否建议对第一个sp执行TRY…CATCH,检查错误号,并执行第二次尝试…捕获不是嵌套的?当阅读有关此解决方案时,我唯一的犹豫是它已被弃用。它建议改为使用链接服务器,这已经到位。有可能让远程过程抛出一个错误,而本地过程捕获它吗?在阅读有关此解决方案的文章时,我唯一的犹豫是它已被弃用。它建议改为使用链接服务器,这已经到位。是否可能让远程过程仅仅抛出一个错误,而本地过程捕获它?远程过程不能包装到事务中,因为没有为此启用支持。我知道
ree建议将多个小程序组合在一起。如果您能够深入了解整个系统体系结构,即sql Server的版本和制造商,以及所使用的连接方法,这将对我们大有帮助。我在那里看到oledb,这对ms sql没有意义,而是使用链接服务器。然后将BEGIN TRANS/COMMIT放在远程存储过程中,这样事务对远程服务器来说是本地的。这一要求也不清楚。您还可以在两台服务器上编程两阶段提交,或者在两台服务器之间设置MS DTC和分布式事务。我将更新更多规范。正如前面的回答所建议的,我回答说,我对实施DTC犹豫不决,因为它已被弃用。弃用并不意味着一旦他们在monthership的深处按下红色按钮,DTC就会立即停止工作。相反,这意味着避免在新版本的产品上实施此解决方案:我已经更新了我的问题。我希望这有帮助。关于组合存储过程,它们在整个月内单独使用。远程过程不能包装到事务中,因为没有为此启用支持。我同意多个小程序应该结合在一起。如果您能提供关于整个系统架构的见解,即sql Server的版本和制造商,以及所使用的连接方法,这将对我们有很大帮助。我在那里看到oledb,这对ms sql没有意义,而是使用链接服务器。然后将BEGIN TRANS/COMMIT放在远程存储过程中,这样事务对远程服务器来说是本地的。这一要求也不清楚。您还可以在两台服务器上编程两阶段提交,或者在两台服务器之间设置MS DTC和分布式事务。我将更新更多规范。正如前面的回答所建议的,我回答说,我对实施DTC犹豫不决,因为它已被弃用。弃用并不意味着一旦他们在monthership的深处按下红色按钮,DTC就会立即停止工作。相反,这意味着避免在新版本的产品上实施此解决方案:我已经更新了我的问题。我希望这有帮助。关于组合存储过程,它们在整个月内单独使用。