shanzm-2020年5月13日

0. 背景说明

之前极其的抱怨使用存储过程,觉得存储过程不应该出现在现在的新项目中,

但是最近研究存储过程,发现存储过程的优点也是及其的耀眼!

之前只盯着存储过程的缺点,有点一叶障目了。

前一周自己摸索着写的存储过程,写的太幼稚了,不规范。

之前在《存储过程——C#中调用存储过程的简单示例》中,

我们在存储过程中的事务中定义了一个临时变量@sum,在事务的每一句sql语句后都@sum+@@error,最后根据@sum是否为0来判断是否有异常,

如果没有异常则@@error为0,有异常则@@error值为错误代码,即一定不为0

所以,可以通过最终的@sum判断是否有异常,

但是有一点要说明的是,@@error对那种重大错误无法捕捉,而且@@error只对其前一句sql语句生效

所以,建议还是使用TRY……CATCH

这里定义一个捕获异常的存储过程,实现将存储过程中出现的异常记录在数据库的异常信息表中。

本示例中,全部的存储过程都是在一个新建的测试数据库ShanTest数据库中进行的



1. 建立异常信息表ErrorLog

  1. USE [ShanTest]
  2. GO
  3. /****** Object: Table [dbo].[ErrorLog] Script Date: 2020-05-11 14:49:33 ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. CREATE TABLE [dbo].[ErrorLog](
  9. [ErrorLogID] [int] IDENTITY(1,1) NOT NULL,--异常表ID
  10. [ErrorTime] [datetime] NOT NULL CONSTRAINT [DF_ErrorLog_ErrorTime] DEFAULT (getdate()),--异常时间,提供默认值就是当前时间
  11. [UserName] [sysname] NOT NULL, --异常用户名,这里就是dbo,dbo是每个数据库的默认用户,具有所有者权限,全称:datebaseOwner
  12. [ErrorNumber] [int] NOT NULL, --异常代码
  13. [ErrorSeverity] [int] NULL, --异常严重性
  14. [ErrorState] [int] NULL, --异常状态码
  15. [ErrorProcedure] [nvarchar](126) NULL, --抛异常的存储过程
  16. [ErrorLine] [int] NULL, --错误行数
  17. [ErrorMessage] [nvarchar](4000) NOT NULL,--完整的异常信息
  18. CONSTRAINT [PK_ErrorLog_ErrorLogID] PRIMARY KEY CLUSTERED
  19. (
  20. [ErrorLogID] ASC
  21. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  22. ) ON [PRIMARY]
  23. GO

异常信息表中字段如下:



2. 建立保存异常信息的存储过程

  1. USE [ShanTest]
  2. GO
  3. /****** Object: StoredProcedure [dbo].[pro_ErrorLog] Script Date: 2020-05-11 14:15:46 ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. -- =================================================
  9. -- Author: shanzm
  10. -- Create date: 2020511
  11. -- Description: 保存存储过程中捕获的异常到ErrorLog
  12. -- =================================================
  13. CREATE PROCEDURE [dbo].[pro_ErrorLog]
  14. @ErrorLogID [int] = 0 OUTPUT
  15. AS
  16. BEGIN
  17. SET NOCOUNT ON;
  18. INSERT INTO [dbo].[ErrorLog]
  19. (
  20. [UserName],
  21. [ErrorNumber],
  22. [ErrorSeverity],
  23. [ErrorState],
  24. [ErrorProcedure],
  25. [ErrorLine],
  26. [ErrorMessage]
  27. )
  28. VALUES
  29. (
  30. CONVERT(sysname, CURRENT_USER),--current_user ,这里值是dbo,dbo是每个数据库的默认用户,具有所有者权限
  31. --sysname类型 用于表列、变量以及用于存储对象名的存储过程参数,等价与nvachart(120)
  32. ERROR_NUMBER(), --错误代号,有很多错误代号,可以自行百度
  33. ERROR_SEVERITY(), --错误的严重性
  34. ERROR_STATE(), --错误的状态码
  35. ERROR_PROCEDURE(), --错误的存储过程
  36. ERROR_LINE(), --错误行号
  37. ERROR_MESSAGE() --错误信息
  38. );
  39. SET @ErrorLogID = @@IDENTITY;--@@IDENTITY 是插入记录时自动产生的ID
  40. execute dbo.pro_PrintError;--改存储过程会将ERROR_MESSAGE()在sql server信息窗口打印出来
  41. END;



3. 建立在SQL Server中打印异常信息的存储过程

在存储过程 pro_ErrorLog 中存储异常信息后,在调用这个存储过程

  1. USE [ShanTest]
  2. GO
  3. /****** Object: StoredProcedure [dbo].[pro_PrintError] Script Date: 2020-05-11 14:43:25 ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. -- =============================================
  9. -- Author: shanzm
  10. -- Create date: 2020511
  11. -- Description: 在消息框中打印异常信息
  12. -- =============================================
  13. CREATE PROCEDURE [dbo].[pro_PrintError]
  14. AS
  15. BEGIN
  16. SET NOCOUNT ON;
  17. -- Print error information.
  18. PRINT 'ErrorNumber : ' +CONVERT(varchar(50), ERROR_NUMBER())
  19. PRINT 'ErrorSeverity : ' + CONVERT(varchar(5), ERROR_SEVERITY())
  20. PRINT 'ErrorState :' + CONVERT(varchar(5), ERROR_STATE())
  21. PRINT 'ErrorProcedure :' + ISNULL(ERROR_PROCEDURE(), '-')
  22. PRINT 'ErrorLine :' + CONVERT(varchar(5), ERROR_LINE());
  23. PRINT 'ErrorMessage :' + ERROR_MESSAGE();
  24. END;



4. 建立一个用于测试的存储过程抛出异常进行测试

切记我们在业务中需要使用存储过程的时候,一旦使用了事务,则我们必须在BEGIN CATCH语句中判断是否有异常抛出,一旦有异常抛出,则存储过程中的事务一定要进行ROLLBACK

  1. USE [ShanTest]
  2. GO
  3. /****** Object: StoredProcedure [dbo].[TestErrorLog] Script Date: 2020-05-11 15:14:11 ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. -- =============================================
  9. -- Author: shanzm
  10. -- Create date: 2020511
  11. -- Description: 用于抛出异常测试ErrorLog是否可用
  12. -- =============================================
  13. ALTER PROCEDURE [dbo].[TestErrorLog]
  14. AS
  15. BEGIN
  16. SET NOCOUNT ON;
  17. BEGIN TRY---------开始捕捉异常
  18. BEGIN TRANSACTION------------------开始事务
  19. update ShanTest.dbo.Product set Name=NULL where Id=1--这里随便建一个数据库,建一个表,给该表中不允许为空的列插入一个NUll
  20. --select 1/0;
  21. COMMIT ----------------------------提交事务
  22. END TRY-----------结束捕捉异常
  23. BEGIN CATCH------有异常被捕获
  24. IF @@TRANCOUNT > 0---------------------判断有没有事务
  25. BEGIN
  26. ROLLBACK --------------------------回滚事务
  27. END
  28. EXEC pro_ErrorLog----------------------执行存储过程将错误信息记录在表当中
  29. END CATCH--------结束异常处理
  30. END

执行改存储过程,进行测试:

  1. USE [ShanTest]
  2. GO
  3. EXEC [dbo].[TestErrorLog]
  4. GO

测试结果:
SQL Serve消息框中现实消息:

  1. ErrorNumber 515
  2. ErrorSeverity 16
  3. ErrorState 2
  4. ErrorProcedure TestErrorLog
  5. ErrorLine 13
  6. ErrorMessage :不能将值 NULL 插入列 'Name',表 'ShanTest.dbo.Product';列不允许有 Null 值。UPDATE 失败。

该消息是由pro_PrintError存储过程打印的

同时ErrorLog表中添加了一条记录:



5. 参考信息

博客园:SQLServer异常捕获
博客园:sqlserver 存储过程 try catch TRANSACTION

存储过程——异常捕获&打印异常信息的更多相关文章

  1. springboot 全局异常捕获,异常流处理业务逻辑

    前言 上一篇文章说到,参数校验,往往需要和全局的异常拦截器来配套使用,使得返回的数据结构永远是保持一致的.参数异常springboot默认的返回结构: { "timestamp": ...

  2. 【快学springboot】5.全局异常捕获,异常流处理业务逻辑

    前言 上一篇文章说到,参数校验,往往需要和全局的异常拦截器来配套使用,使得返回的数据结构永远是保持一致的.参数异常springboot默认的返回结构: { "timestamp": ...

  3. T-SQL编程中的异常处理-异常捕获(catch)与抛出异常(throw)

    本文出处: http://www.cnblogs.com/wy123/p/6743515.html T-SQL编程与应用程序一样,都有异常处理机制,比如异常的捕获与异常的抛出,本文简单介绍异常捕获与异 ...

  4. T-SQL编程中的异常处理-异常捕获(try catch)与抛出异常(throw)

    本文出处: http://www.cnblogs.com/wy123/p/6743515.html T-SQL编程与应用程序一样,都有异常处理机制,比如异常的捕获与异常的抛出(try catch th ...

  5. 电脑小白学习软件开发-C#的选择语句、异常捕获,进攻程序员

    写代码也要读书,爱全栈,更爱生活.每日更新原创IT编程技术及日常实用视频. 我们的目标是:玩得转服务器Web开发,搞得懂移动端,电脑客户端更是不在话下. 不得不说,C#这门语言是小编以为最好的语言.其 ...

  6. Flask基础(08)-->错误捕获(异常捕获)

    错误捕获(异常捕获) from flask import Flask from flask import abort app = Flask(__name__) @app.route('/demo1' ...

  7. 请对比 Exception 和 Error,另外,运行时异常与一般异常有什么区别?

    error指的是不可预料的错误,可能会导致程序宕机:而exception指的是在程序运行中可以预见的异常,而异常分为检查异常与一般异常,检查异常需要在程序中显示捕获并处理,一般异常可以通过程序编码来进 ...

  8. sql存储过程异常捕获并输出例子还有不输出过程里面判断异常 例子

    编程的异常处理很重要,当然Sql语句中存储过程的异常处理也很重要,明确的异常提示能够快速的找到问题的根源,节省很多时间. 下面,我就以一个插入数据为例来说明Sql Server中的存储过程怎么捕获异常 ...

  9. Slf4j打印异常的堆栈信息

    一.前言 直接用logger.info("异常信息为:"+e)或者logger.info(e.getMessage())只能记录到异常的描述信息,却没有其异常具体发生在哪一行代码. ...

随机推荐

  1. ROM定制开发教程-Android adb命令用法与实例解析

    一.什么是ADB Android Debug Bridge(adb)是一个命令行工具,可让您与模拟器或连接的Android设备进行通信.您可以在android sdk / platform-tools ...

  2. Cucumber(2)——目录结构以及基本语法

    目录 回顾 HelloWorld 扩展 回顾 在上一节中,我大致的介绍了一下cucumber的特点,以及基于ruby和JavaScript下关于cucumber环境的配置,如果你还没有进行相关的了解或 ...

  3. Gradle系列之Groovy基础篇

    原文发于微信公众号 jzman-blog,欢迎关注交流. 上一篇学习了 Gradle 的入门知识,Gradle 基于 Groovy,今天学习一下 Groovy 的基础知识,Groovy 是基于 JVM ...

  4. vue2.x学习笔记(七)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12576797.html. 条件渲染 vue也提供了一些指令,用于条件性地渲染模板中的内容. [v-if]和[v-e ...

  5. 4. css事件

    可通过使用css伪类实现点击元素变色的效果,两个伪类是:active, :focus :active :active选择器用于选择活动链接.当在一个链接上点击时,它就会成为活动的(激活的),:acti ...

  6. jmeter事务控制器

    jmeter事务控制器常用于压力测试时如果一个功能包括多个请求时,需要测试这个功能的压力情况,则需要把多个请求放到一个事务控制器里面

  7. TeamViewer11 万全免费

    下载地址:百度网盘 c4xm TeamViewer 是一款简单易用且功能强大的远程控制软件,它能穿越内网,摆脱路由器或防火墙的限制,任何一方都不需要拥有固定IP地址.让不懂技术的朋友也能远程控制电脑, ...

  8. hadoop 伪分布配置

    配置 Hadoop 伪分布式 任务配置说明: VMware 15 Centos 6.5 java -jdk 1.8 hadoop-2.6.0-cdh5.14.0.tar.gz 第一步 自行安装虚拟机 ...

  9. PSD转HTML

    随着时间的推移,技术的进步,越来越多的人也越来越熟悉HTML和CSS以及不同的技术来将 Photoshop 设计转换成 HTML 或 CSS 格式.对于一个设计师或网页开发人员,知道如何将PSD文件转 ...

  10. zabbix监控ftp

    [root@agent ~]# yum -y install vsftpd [root@agent ~]# systemctl start vsftpd[root@agent ~]# systemct ...