65.9K
CodeProject 正在变化。 阅读更多。
Home

SQL Server 错误详细信息。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (18投票s)

2014 年 9 月 22 日

CPOL

4分钟阅读

viewsIcon

27623

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 如何响应错误?
以下是 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 中的错误处理模板”,以了解错误处理模板。

历史

在此处保持您所做的任何更改或改进的实时更新。

© . All rights reserved.