KM.*_*KM. 35 t-sql sql-server error-handling sql-server-2005
我们有一个大型应用程序,主要用SQL Server 7.0编写,其中所有数据库调用都是存储过程.我们现在运行SQL Server 2005,它提供了更多的T-SQL功能.
在几乎所有SELECT,INSERT,UPDATE和DELETE之后,@@ ROWCOUNT和@@ ERROR被捕获到局部变量中并对问题进行评估.如果出现问题,则执行以下操作:
它们都不检查行(只有在知道的情况下),并且一些不同的日志/调试信息或多或少.此外,行逻辑是从错误逻辑拆分的某些时间(在更新中,在WHERE子句中检查并发字段,行= 0表示其他人已更新数据).但是,这是一个相当通用的例子:
SELECT, INSERT, UPDATE, or DELETE
SELECT @Error=@@ERROR, @Rows=@@ROWCOUNT
IF @Rows!=1 OR @Error!=0
BEGIN
SET @ErrorMsg='ERROR 20, ' + ISNULL(OBJECT_NAME(@@PROCID), 'unknown')
+ ' - unable to ???????? the ????.'
IF @@TRANCOUNT >0
BEGIN
ROLLBACK
END
SET @LogInfo=ISNULL(@LogInfo,'')+'; '+ISNULL(@ErrorMsg,'')+
+ ' @YYYYY=' +dbo.FormatString(@YYYYY)
+', @XXXXX=' +dbo.FormatString(@XXXXX)
+', Error=' +dbo.FormatString(@Error)
+', Rows=' +dbo.FormatString(@Rows)
INSERT INTO MyLogTable (...,Message) VALUES (....,@LogInfo)
RETURN 20
END
Run Code Online (Sandbox Code Playgroud)
我正在考虑用TRY-CATCH T-SQL替换我们如何做到这一点.我已经阅读了TRY ... CATCH(Transact-SQL)语法,所以不要只发布一些摘要.我正在寻找任何好的想法,以及如何最好地做或改进我们的错误处理方法.它不一定是Try-Catch,只是任何使用T-SQL错误处理的好或最佳实践.
Joe*_*orn 31
你应该读这个:
http://www.sommarskog.se/error-handling-I.html
我不能足够推荐这个链接.这有点长,但是好的方式.
前面有一个免责声明,它最初是为SQL Server 2000编写的,但它也涵盖了SQL Server 2005+中新的try/catch错误处理能力.
mar*_*c_s 24
我们目前将此模板用于我们执行的任何查询(如果您在例如DDL语句中不需要它,则可以省略事务内容):
BEGIN TRANSACTION
BEGIN TRY
// do your SQL statements here
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage
ROLLBACK TRANSACTION
END CATCH
Run Code Online (Sandbox Code Playgroud)
当然,您可以轻松地将捕获的异常插入到错误日志表中.
它对我们来说非常有效.您甚至可以使用代码生成(例如CodeSmith)或一些自定义C#代码自动执行从旧存储过程到新格式的一些转换.
错误处理没有一套完整的最佳实践.这一切都归结为您的需求和一致性.
以下是存储电话号码的表和存储过程的示例.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Phone](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Phone_Type_ID] [int] NOT NULL,
[Area_Code] [char](3) NOT NULL,
[Exchange] [char](3) NOT NULL,
[Number] [char](4) NOT NULL,
[Extension] [varchar](6) NULL,
CONSTRAINT [PK_Phone] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/**/
CREATE PROCEDURE [dbo].[usp_Phone_INS]
@Customer_ID INT
,@Phone_Type_ID INT
,@Area_Code CHAR(3)
,@Exchange CHAR(3)
,@Number CHAR(4)
,@Extension VARCHAR(6)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @Err INT, @Phone_ID INT
BEGIN TRY
INSERT INTO Phone
(Phone_Type_ID, Area_Code, Exchange, Number, Extension)
VALUES
(@Phone_Type_ID, @Area_Code, @Exchange, @Number, @Extension)
SET @Err = @@ERROR
SET @Phone_ID = SCOPE_IDENTITY()
/*
Custom error handling expected by the application.
If Err = 0 then its good or no error, if its -1 or something else then something bad happened.
*/
SELECT ISNULL(@Err,-1) AS Err, @Phone_ID
END TRY
BEGIN CATCH
IF (XACT_STATE() <> 0)
BEGIN
ROLLBACK TRANSACTION
END
/*
Add your own custom error handling here to return the passed in paramters.
I have removed my custom error halding code that deals with returning the passed in parameter values.
*/
SELECT ERROR_NUMBER() AS Err, ISNULL(@Phone_ID,-1) AS ID
END CATCH
END
Run Code Online (Sandbox Code Playgroud)