SQL Server 错误详细信息。






4.81/5 (18投票s)
SQL Server 错误解剖概述。
引言
在任何编程中,异常都是不可避免的。为了使我们的应用程序健壮,我们需要实现某种错误处理方式。因此,我们也需要关注数据库脚本中的错误处理。本文重点介绍 SQL Server 错误以及它如何响应错误。在下一篇文章中,我们将有一个很好的模板来管理存储过程和函数中的错误。
让我们来剖析一下错误
让我们从错误消息的解剖开始。
1:错误消息编号:
每个错误都有一个唯一的编号。我们可以在 Master 数据库下的 sysmessages 表中找到所有系统定义的错误。错误编号小于 50K 的是系统定义的。默认情况下,RAISERROR 的错误消息编号为 50000。
RAISERROR('This is an error', 16, 1)
我们可以使用系统定义的存储过程 sp_addmessge 添加自定义错误消息。
SELECT * FROM sysmessages
EXEC sp_addmessage @msgnum = 50003, @severity = 11, @msgtext='My Own Error'
SELECT * FROM sysmessages
我们可以使用 sp_dropmessage 删除自定义消息。
SELECT * FROM sysmessages
EXEC sp_dropmessage @msgnum = 50003
SELECT * FROM sysmessages
2:严重性级别:
这是一个 1 到 25 之间的数字。
0-10 是警告或信息性错误。
11-16 用于显示编程错误。
17-25 显示资源/硬件/操作系统/SQL Server 内部错误
严重性级别较高的错误消息被认为是致命的。这里有一篇关于此的精彩文章,来自 这里
3:错误状态:
这是一个整数值。如果同一错误在代码的不同点引发,我们可以使用错误状态来区分引发错误的脚本部分。
假设我们有类似以下的条件
IF <condition1>
RAISERROR(N'Error raised for condition1', 16, 0);
IF <condition2>
RAISERROR(N'Error raised for condition2', 16, 1);
GO
4:过程:
这显示了哪个存储过程、用户定义函数或触发器引发了错误。如果错误发生在批处理语句中,则此项为空。
5:错误行:
这显示了 SP/UDF/批处理中导致错误的语句的行号。如果 SP/UDF 调用导致错误,则为 0。
6:错误消息:
这是开发人员最重要的事情。它显示实际的错误消息。
以下是 SQL Server 在发生错误时可能采取的四种主要操作。
人们普遍认为,一旦脚本批处理中发生错误,下一行默认情况下就不会被执行。
1:语句终止
SQL Server 终止导致错误的语句,但会继续执行下一条语句。如果存在未回滚的开放事务,则事务不受影响。重复的主键、非空约束冲突、检查约束或外键约束违反、对表或 SP 的权限被拒绝、算术溢出错误是导致语句终止的一些错误。
让我们做一个小演示。
让我们创建一个表,可用于所有演示目的。
--Create a Table Book
CREATE TABLE dbo.Book
(
BookID INT NOT NULL PRIMARY KEY,
Name NVARCHAR (100) NOT NULL,
Price Money NOT NULL
)
GO
让我们向此表中插入具有重复主键值的插入数据。
--Here we will get statement Abortion
PRINT 'Beginning of execution'
INSERT INTO Book(BookID, Name , Price)
VALUES(1, 'Demo Book1', 100)
INSERT INTO Book(BookID, Name , Price)
VALUES(1, 'Demo Book2', 200)
PRINT 'End of execution'
这里错误发生在第二个 INSERT 语句上,但最后一个 PRINT 语句已执行。下面是输出。
2:作用域中止
在这里,SQL Server 终止当前作用域中的所有语句,并继续执行作用域外部引发错误的语句。当前作用域是指存储过程、用户定义函数或 SQL 语句块,包括动态 SQL。
让我们做一个演示。
--Here we will get Scope Abortion PRINT 'Beginning of Scope execution' EXEC('SELECT BookID FROM BOOKs') --SELECT query executed dynamically. PRINT 'End of Scope execution' GO
在这里,我们尝试使用动态 SQL 从不存在的表中选择数据。动态脚本执行会将脚本带到另一个作用域,因此我们会得到语句终止错误操作,并且最后的 PRINT 语句已执行。
3:批处理终止
整个客户端调用的执行被终止。如果存在任何开放事务,则会将其回滚。这主要发生在大多数转换错误时,例如当我们尝试将非数字字符串转换为数字时、死锁问题、执行 SP 或向表中插入数据时参数数量不匹配。
--Here we will get Batch Abortion
PRINT 'Beginning of Batch execution'
SELECT BookID FROM BOOKs
PRINT 'End of Batch execution'
GO
这会导致批处理中止,并且最后一条语句未执行。
4:连接终止
此错误操作发生在严重性级别 20-25 的错误时。此时客户端会断开连接,并且任何开放事务都会回滚。这仅发生在 SQL Server 发生严重问题时,例如硬件问题、网络问题、数据库损坏或严重的资源问题。
5:XACT_ABORT
我们可以将其设置为 ON 或 OFF。默认值为 OFF。因此,在这种情况下,SQL Server 将根据错误的严重性级别决定该怎么做。SET XACT_ABORT ON 指示 SQL Server 终止整个事务。
让我们做一个关于它的一个小演示。
CREATE PROCEDURE dbo.XactAbortONSP
AS
BEGIN
SET XACT_ABORT ON
PRINT 'Beginning of execution'
EXEC MissingSP --This SP doesnot exist
PRINT 'End of execution'
END
让我们运行 SP
EXEC XactAbortONSP
下面是输出。
这里我们尝试执行不存在的存储过程,这导致了语句终止。
但是我们设置了 SET XACT_ABORT ON,因此它终止了整个语句批处理。
现在让我们通过 SET XACT_ABORT OFF 演示来检查。
CREATE PROCEDURE dbo.XactAbortOFFSP
AS
BEGIN
SET XACT_ABORT OFF
PRINT 'Beginning of execution'
EXEC MissingSP --This SP doesnot exist
PRINT 'End of execution'
END
让我们运行 SP。
EXEC XactAbortOFFSP
这里我们得到了语句终止错误操作。总而言之,我们可以说 SET XACT_ABORT ON 会将语句终止错误操作变为批处理终止错误操作。
结论。
我认为我们从这篇文章中学到了一些新东西。如果有什么错误,请纠正我,以便我能改正。这是我的第一篇文章。所以,我需要您的建议和反馈来提高这篇文章以及后续文章的质量。请看看我的提示“SQL Server 中的错误处理模板”,以了解错误处理模板。
历史
在此处保持您所做的任何更改或改进的实时更新。