当前位置: 首页 > news >正文

sqlserver怎样动态执行存储过程,并且返回报错

存储过程1

USE [OM]
GO
/****** Object:  StoredProcedure [dbo].[procTranDemo2]    Script Date: 2025/6/24 19:20:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GOCREATE PROCEDURE [dbo].[procTranDemo2]@wo VARCHAR(255),@cartonId VARCHAR(255) OUTPUT
AS
DECLARE @sql VARCHAR(100);
DECLARE @errorMsg VARCHAR(4000);
DECLARE @SavePoint VARCHAR(32) = 'SP_' + CAST(@@SPID AS VARCHAR);
BEGIN
SET NOCOUNT ON; -- 禁用受影响行数的消息返回
SAVE TRANSACTION @SavePoint; 
BEGIN TRYPRINT @wo;--set @sql = 'delete from mes_zhiju_box where box_id = ''test'''--print @sql--exec(@sql)THROW 51000, '动态sql报错', 1;--select 'key1' as 'label_key', 'value1' as 'label_value'SET @cartonId = 'test0001';END TRY
BEGIN CATCHPRINT 'demo2';PRINT @@TRANCOUNT;SET @errorMsg = ERROR_MESSAGE();ROLLBACK TRANSACTION @SavePoint;-- 重新抛出原始错误(保留堆栈)THROW;
END CATCH
END

存储过程2

USE [OM]
GO
/****** Object:  StoredProcedure [dbo].[procTranDemo]    Script Date: 2025/6/24 19:20:12 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GOALTER PROCEDURE [dbo].[procTranDemo]@wo varchar(255),@cartonId VARCHAR(255) OUTPUT
AS
DECLARE @sql NVARCHAR(MAX);
DECLARE @errorMsg VARCHAR(4000);
DECLARE @errorCode INT;
BEGIN
SET NOCOUNT ON; -- 禁用受影响行数的消息返回
BEGIN TRY;BEGIN TRAN;DECLARE @paramDefinition NVARCHAR(500);DECLARE @procName VARCHAR(50) = 'procTranDemo2';SET @sql = N'DECLARE @innerError INT, @innerMessage VARCHAR(4000);BEGIN TRY-- 执行目标存储过程EXEC '+ @procName +'@wo = '''+ @wo +''',@cartonId = @cartonId OUTPUTEND TRYBEGIN CATCH-- 捕获存储过程内部异常SET @innerError = ERROR_NUMBER();SET @innerMessage = ERROR_MESSAGE();END CATCH;-- 传递错误信息到外层SELECT @errorCode = @innerError, @errorMsg = @innerMessage;';SET @paramDefinition = N'@cartonId VARCHAR(100) OUTPUT,@errorCode INT OUTPUT,@errorMsg VARCHAR(4000) OUTPUT';EXEC sp_executesql @sql,                       -- 动态SQL字符串@paramDefinition,                  -- 参数定义@cartonId = @cartonId OUTPUT, -- 绑定:动态参数 -> 外部变量@errorCode = @errorCode OUTPUT,@errorMsg = @errorMsg OUTPUT;IF(@errorCode IS NOT NULL OR @errorMsg IS NOT NULL)BEGIN-- 自定义错误处理(如记录日志)PRINT '存储过程内部错误: ' + COALESCE(@errorMsg, '未知错误');-- 重新抛出错误THROW 51000, @errorMsg, 1;END;IF(@@TRANCOUNT > 0)BEGINCOMMIT TRAN;END 
END TRY
BEGIN CATCHPRINT 'demo1';PRINT @@TRANCOUNT;IF(@@TRANCOUNT > 0)BEGINSET @errorMsg = ERROR_MESSAGE()ROLLBACK TRANSACTIONEND;-- 重新抛出原始错误(保留堆栈)THROW;
END CATCH
END

讲解

我们需要在存储过程2中动态调用存储过程1,这里面着重需要注意的是事务的管理,首先事务嵌套事务,当内部事务报错时,我们一般会执行回滚,那么一回滚就会连同外部的事务也一起回滚掉了,执行时就会报错。

所以我在存储过程1(内部)中使用了保存点回滚,而在存储过程2(外部)中使用了事务回滚。

还有THROW这个关键字的使用,你可以先记住它就是抛出异常、中断批处理。其余的你可以百度它的深层意思。

http://www.lqws.cn/news/510445.html

相关文章:

  • 解决ptmalloc2内存过大的三种方案
  • 使用GDB调试程序方法
  • 02-Linux内核源码编译
  • java语言中的XML解析
  • 解决Fedora21下无法使用NWJS网页透明效果的问题
  • mybatisPlus动态表前缀
  • 磁悬浮轴承遇上“热浪”挑战:多参数自适应补偿策略揭秘
  • [学习] C语言编程中线程安全的实现方法(示例)
  • day041-web集群架构搭建
  • 棋盘格标定板和圆形标定板的优劣性
  • windows 上 build 时,微软给出的 vcpkg 工具,如何使用
  • MySQL 8.x配置MGR高可用+ProxySQL读写分离(三):配置ProxySQL主从分组信息
  • [3D-Portfolio] docs | js集中式配置 | React组件 | 组件嵌套
  • [附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+jsp实现的超市库存商品管理系统,推荐!
  • 16、nrf52840蓝牙学习(唯一ID加密与解密)
  • 华为认证预约考试、考试时长、取消/改期、补考时间汇总
  • C++ <vector>
  • Redis 乱码和LocalDateTime类型缓存问题
  • 鸿蒙开发深入解析:Data Ability 数据共享机制全面指南
  • 工业弧焊机器人气保焊节气装置
  • 搭建智能问答系统,有哪些解决方案,比如使用Dify,LangChain4j+RAG等
  • 【Altium】原理图位号自动标注
  • spring中的切面类实践
  • WPF CommunityToolkit.Mvvm
  • 【技术难题】el-table的全局数据排序实现示例,不受分页影响,以及异步请求带来的页面渲染问题
  • 针对基于深度学习的侧信道分析(DLSCA)进行超参数的贝叶斯优化
  • VIVADO导出仿真数据到MATLAB中进行分析
  • python基础(字符串-复习)
  • 关于素数、唯一分解等内容的详细讲解(从属于GESP五级)
  • vscode + Jlink 一键调试stm32 单片机程序(windows系统版)