SQL Server里raiserror和throw有啥不一样?看完这篇你就懂了!

吉云

今天来聊聊我捣鼓 raiserror 的那点事儿。这玩意儿,说白,就是在 SQL Server 里头,你想让它给你报个错,或者说,你想手动触发一个错误信息的时候,就能用上它。

初次接触这玩意儿

记得刚开始那会儿,我写存储过程,有时候,业务逻辑走到某个分支,发现条件不对,比如用户传进来的参数有问题,或者某个关键数据找不着。我总不能让程序就这么稀里糊涂地继续跑下去?得告诉调用我这个存储过程的程序,“喂,哥们儿,你这儿出问题!”

SQL Server里raiserror和throw有啥不一样?看完这篇你就懂了!

一开始我可能就简单地 SELECT 一个错误信息回去,但感觉不太对劲,那不算是个正经的“错误”。后来翻资料,或者看别人的老代码,就撞见 raiserror 这家伙。一看,诶,这好像就是专门干这个的。

上手试试

那就试试呗。最简单的,就是直接抛一个自己写的错误信息。比如:

raiserror('你提供的那个用户ID不存在!', 16, 1)

这后面跟的 161 是啥?

    SQL Server里raiserror和throw有啥不一样?看完这篇你就懂了!

  • 第一个数字,16,是错误的“严重级别”。我看文档说,16 大概意思就是用户可以修正的错误,挺常用的。级别低点儿的,可能就是个信息或者警告,级别再高上去,那就可能是数据库本身出大问题。一般咱自己定义的业务错误,用 11 到 16 好像比较多。
  • 第二个数字,1,是“状态”。这个,好像是在同一个错误有好几种可能的原因时,用来区分具体是哪一种的。早期我没太在意,就随便写个 1。

试下,果然,执行到这句,存储过程就停,然后调用它的地方就能捕获到这个错误信息。感觉挺好用! 这样就能明确地把业务逻辑上的问题,以“错误”的形式通知给应用程序,应用程序那边就可以根据这个错误信息来做相应的处理,比如给用户一个友好的提示。

捣鼓更复杂点的

后来我又琢磨,老是写死错误信息也不方便,有时候我想把动态的数据,比如哪个 ID 找不到,给包含在错误信息里。raiserror 也能做到,语法有点像 C 语言的 printf

SQL Server里raiserror和throw有啥不一样?看完这篇你就懂了!

declare @MissingItemID int = 123;
raiserror('注意,ID号是 %d 的这个东西没找到!', 16, 1, @MissingItemID);

你看,用 %d 占位符,然后把变量 @MissingItemID 传进去,错误信息里就能动态显示具体是哪个 ID 丢。这个功能我觉得特别实用。

我还解到,可以预先把错误信息定义在系统里,用 sp_addmessage 加进去,得到一个错误号(大于 50000 的),然后 raiserror 直接用这个号就行,这样管理起来更规范,尤其是在错误信息需要多语言支持的时候。不过我自己平时写的小东西,直接写消息字符串的时候更多点儿,图个省事。

后来知道 THROW

再后来SQL Server 版本也更新嘛好像是从 SQL Server 2012 开始,出个新的东西叫 THROW。这玩意儿用起来更像是咱们在 C# 或者 Java 里写代码抛异常的感觉。

SQL Server里raiserror和throw有啥不一样?看完这篇你就懂了!

比如,配合 TRY...CATCH 结构:

BEGIN TRY
-- 这里是可能出错的代码
IF @SomeConditionIsBad = 1
THROW 50001, '某个条件不满足,处理不!', 1;
END TRY

SQL Server里raiserror和throw有啥不一样?看完这篇你就懂了!

BEGIN CATCH
-- 这里可以记录日志,或者重新抛出错误
THROW; -- 这个不带参数的 THROW 能重新抛出被 CATCH 捕获到的原始错误
END CATCH

THROW 语法上感觉是比 raiserror 要简洁那么一点点,而且它不需要指定那个状态码(虽然也能指定)。特别是那个不带参数的 THROW;,在 CATCH 块里用着很方便,能把抓到的异常原封不动地再扔出去。

现在要是我写新的存储过程,尤其是在比较新的 SQL Server 版本上,我可能更倾向于用 TRY...CATCH...THROW 这套组合拳。感觉逻辑更清晰,也更符合现代编程语言的异常处理习惯。

SQL Server里raiserror和throw有啥不一样?看完这篇你就懂了!

总结一下

不过话说回来,raiserror 并没有被淘汰。大量的、年头久远的代码里,你还是会经常看到它的身影。 搞明白它是怎么回事,怎么用的,还是非常有必要的,不然维护老系统的时候会一头雾水。

raiserror 就是 SQL Server 提供的一个挺有用的工具,让咱们能在数据库层面主动地、明确地抛出错误,控制程序的流程。虽然现在有更“时髦”的 THROW,但解 raiserror 的实践过程和用法,对理解 SQL Server 的错误处理机制还是很有帮助的。这就是我折腾 raiserror 的一些经历和记录。

免责声明:由于无法甄别是否为投稿用户创作以及文章的准确性,本站尊重并保护知识产权,根据《信息网络传播权保护条例》,如我们转载的作品侵犯了您的权利,请您通知我们,请将本侵权页面网址发送邮件到qingge@88.com,深感抱歉,我们会做删除处理。

目录[+]