主にSQL Server 7.0で記述された大規模なアプリケーションがあり、すべてのデータベース呼び出しはストアドプロシージャに対して行われます。 現在、より多くのT-SQL機能を提供するSQL Server 2005を実行しています。
ほぼすべてのSELECT、INSERT、UPDATE、およびDELETEの後、@@ ROWCOUNTおよび@@ ERRORがローカル変数にキャプチャされ、問題が評価されます。問題がある場合、次のことが行われます。
それらはすべて行をチェックせず(既知の場合のみ)、ログ/デバッグ情報が多少異なります。また、行ロジックはエラーロジックから分割されています(WHERE句で同時実行フィールドがチェックされる更新では、rows = 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
これをTRY-CATCH T-SQLに置き換える方法を検討しています。 TRY ... CATCH(Transact-SQL) 構文について読んだことがあるので、単に要約を投稿するだけではありません。エラー処理方法を実行または改善するための良いアイデアと方法bestを探しています。 Try-Catchである必要はなく、T-SQLエラー処理の適切な使用またはベストプラクティスの使用だけです。
あなたはこれを読むべきです:
http://www.sommarskog.se/error-handling-I.html
そのリンクを十分に推奨することはできません。少し長いですが、良い意味で。
最初にSQL Server 2000用に作成されたという免責事項がありますが、SQL Server 2005+の新しいtry/catchエラー処理機能についても説明しています。
現在、このテンプレートは、実行するクエリに使用します(DDLステートメントなどで必要ない場合は、Transactionのものを省略できます)。
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
もちろん、キャッチした例外をエラーログテーブルに簡単に挿入できます。
それは私たちにとって本当にうまくいきます。コード生成(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
あなたはすでにこれについて非常に良いハンドルを持っているようです。 SQLプログラマーの95%以上が世に出ていると思います。
ここで興味深い情報を見つけることができます:
[関連のない]提案:「!=」の代わりに「<>」の使用を開始します。
[* SQL Junkiesは廃止されたため、2番目の記事は利用できません。どこかに再公開して、リンクを更新しようとします。]