SQLストアドプロシージャは非常に興味深く、有用であることがわかりました。私はストアドプロシージャを作成しましたが、あらゆる要件に対応できるように巧妙に作成された、パフォーマンスが調整された簡潔なSPを作成したいと思います。ストアドプロシージャを作成するときに、初心者から上級者向けの段階にどのように移動しますか?
更新:私の質問はより具体的である必要があるというコメントから見つかりました。誰もが彼らの袖の上にいくつかのトリックを持っています、そして私は彼らが他のものと区別し、そしてより重要なことに、彼らをコードで使用するSPのためのそのようなトリックと実践を期待していましたストアドプロシージャの作成と操作の生産性。
これが私のストアドプロシージャのエラー処理ガイドラインです。
ストアドプロシージャを実行するときは、必ず@@ errorと戻り値の両方を確認してください。例えば:
EXEC @err = AnyStoredProc @value
SET @save_error = @@error
-- NULLIF says that if @err is 0, this is the same as null
-- COALESCE returns the first non-null value in its arguments
SELECT @err = COALESCE( NULLIF(@err, 0), @save_error )
IF @err <> 0 BEGIN
-- Because stored proc may have started a tran it didn't commit
ROLLBACK TRANSACTION
RETURN @err
END
次のステートメントの後は常に@@ errorを保存して確認してください。
INSERT, DELETE, UPDATE
SELECT INTO
Invocation of stored procedures
invocation of dynamic SQL
COMMIT TRANSACTION
DECLARE and OPEN CURSOR
FETCH from cursor
WRITETEXT and UPDATETEXT
私が常に使用しようとする唯一のトリックは、次のとおりです。常に上部近くのコメントに使用例を含めてください。これは、SPのテストにも役立ちます。私は最も一般的な例を含めるのが好きです-それはサーバーのすぐそこに保存されているので、お気に入りの呼び出しでSQLプロンプトや個別の.sqlファイルを必要とすることもありません(これは、 sp_whoは、ブロックまたはその他のものを出力し、一連のパラメーターを取ります)。
何かのようなもの:
/*
Usage:
EXEC usp_ThisProc @Param1 = 1, @Param2 = 2
*/
次に、SPをテストまたは実行するには、スクリプトでそのセクションを強調表示して実行するだけです。
悪い:
SET NOCOUNT ON
BEGIN TRAN
INSERT...
UPDATE...
COMMIT
より良いですが、乱雑に見え、コーディングするのに大きな苦痛があります:
SET NOCOUNT ON
BEGIN TRAN
INSERT...
IF @ErrorVar <> 0
BEGIN
RAISERROR(N'Message', 16, 1)
GOTO QuitWithRollback
END
UPDATE...
IF @ErrorVar <> 0
BEGIN
RAISERROR(N'Message', 16, 1)
GOTO QuitWithRollback
END
EXECUTE @ReturnCode = some_proc @some_param = 123
IF (@@ERROR <> 0 OR @ReturnCode <> 0)
GOTO QuitWithRollback
COMMIT
GOTO EndSave
QuitWithRollback:
IF (@@TRANCOUNT > 0)
ROLLBACK TRANSACTION
EndSave:
良い:
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRY
BEGIN TRAN
INSERT...
UPDATE...
COMMIT
END TRY
BEGIN CATCH
IF (XACT_STATE()) <> 0
ROLLBACK
END CATCH
ベスト:
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
INSERT...
UPDATE...
COMMIT
では、「最善の」ソリューションのエラー処理はどこにあるのでしょうか。何も必要ありません。 SET XACT_ABORT ONを参照してください。これは、エラーが発生した場合に自動ロールバックを実行することを意味します。コードはより簡潔で読みやすく、書きやすく、バグが少ないです。 SQL Serverがこれを行うので、エラー状態を見逃す可能性がないため、バグが少なくなります。
これは非常に一般的な質問ですが、ここではいくつかのアドバイスを示します。
もちろん、それだけではありません。詳細は次のとおりです。 SQL Serverストアドプロシージャの最適化のヒント
SQL Serverでは、プロシージャが存在する場合はそれを削除するステートメントを常に挿入しているので、開発中にプロシージャを簡単に再作成できます。何かのようなもの:
IF EXISTS(SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'usp ')AND type in(N'P'、N'PC ')) DROP PROCEDURE usp
これは、ストアドプロシージャで何をしているのかに大きく依存します。ただし、1つのプロシージャで複数の挿入/更新または削除を行う場合は、トランザクションを使用することをお勧めします。このようにして、1つの部分に障害が発生した場合、他の部分はロールバックされ、データベースは一貫した状態になります。
データベースに書き込むとき(つまり、選択以外のアクションを実行するストアドプロシージャを使用するとき)に考慮すべき最も重要な2つのことは、データの整合性とパフォーマンスです。データの整合性がないと、ゴミが含まれていて役に立たないデータベースしかありません。 performacneがないと、ユーザー(クライアントの外部にいる場合)や不幸なユーザー(製品の使用が義務付けられている場合、通常は他の場所に行く選択肢のない内部ユーザー)がなくなります。どちらもあなたのキャリアに適していません。そのため、ストアドプロシージャを作成する場合は、まずデータがデータベースに正しく入力され、アクションの一部に問題がある場合は失敗することを確認してください。
最終結果が正しいことを確認するために、必要に応じてチェックをプロシージャに書き込みます。私はETLスペシャリストであり、データをテーブルにインポートする前に、データをクリーンアップして正規化するように常にprocを作成しています。ユーザーインターフェイスから何かを実行している場合、これはprocで行うことはそれほど重要ではないかもしれませんが、データを挿入するためにデータが適切であることを確認するためにprocを実行する前にユーザーインターフェースでチェックを行う必要があります(確認するためのチェックなど)日付フィールドには実際の日付が含まれ、すべての必須フィールドには値が含まれている、など)
大量のデータをテーブルに格納するプロシージャを作成する場合は、ファイナライズされる前にそれらの結果をテストする方法を用意するのが最善です。データのインポートのためにクライアントやベンダーから入手するジャンクに驚かれることでしょう。すべてのインポートプロシージャをテストフラグで記述します。そうすることで、アクションを実行するのではなく、選択したデータを返すことができるため、影響を受けるものを正確に事前に確認できます。
私は動的SQLのファンではなく、ストアドプロシージャで使用することは好みません。既存のプロシージャで動的SQlに行き詰まっている場合は、SQLを実行するのではなく出力できるようにするデバッグフラグを設定してください。次に、実行する必要がある最も一般的なケースをコメントに入力します。これを行えば、プロシージャをより適切に維持できることがわかります。
一度に1つのレコードでのみ機能する別のストアドプロシージャを再利用するために、カーソルで処理を実行しないでください。悪いことにパフォーマンスの問題を引き起こすコードの再利用。
Caseステートメントまたはifステートメントを使用している場合は、可能なすべてのブランチにヒットするテストを行っていることを確認してください。テストしないものは失敗するものです。
これは、詳細情報がなくても直接回答できる質問ではありませんが、いくつかの一般的な経験則が実際に適用されます。
ストアドプロシージャは、単に格納されているT-SQLクエリです。したがって、T-SQLおよびさまざまな関数と構文に慣れることが、実際に行う必要があることです。さらに、パフォーマンスの観点から見ると、クエリと基になるデータ構造が適切なパフォーマンスを可能にする方法で一致することを確認する必要があります。 IE、インデックス、関係、制約などが必要な場所に実装されていることを確認してください。
パフォーマンスチューニングツールの使用方法の理解、実行プランの機能の理解、およびその性質から、「次のレベル」に到達する方法
SQL Server 2008では、TRY ... CATCH構文を使用します。これをT-SQLストアドプロシージャ内で使用して、@@ ERRORをチェックすることで、SQL Serverの以前のバージョンで利用できたよりも優れたメカニズムを例外処理に提供できます(多くの場合、各SQLステートメントの後のGOTOステートメントの使用)。
BEGIN TRY
one_or_more_sql_statements
END TRY
BEGIN CATCH
one_or_more_sql_statements
END CATCH
CATCHブロック内では、次のエラー関数を使用して、CATCHブロックを呼び出したエラーに関する情報を取得できます。
ERROR_NUMBER()
ERROR_MESSAGE()
ERROR_SEVERITY()
ERROR_STATE()
ERROR_LINE()
ERROR_PROCEDURE()
実行される各ステートメントによってリセットされる@@ errorとは異なり、エラー関数によって取得されるエラー情報は、TRY ... CATCHステートメントのCATCHブロックのスコープ内のどこでも一定のままです。これらの関数を使用すると、エラー処理を単一のプロシージャにモジュール化できるため、すべてのCATCHブロックでエラー処理コードを繰り返す必要がありません。
以下は、いくつかのベストプラクティスです。
SQL ServerにマルチレベルのROLLBACKがないことを証明するコードと、トランザクションの処理方法を次に示します。
BEGIN TRAN;
SELECT @@TRANCOUNT AS after_1_begin;
BEGIN TRAN;
SELECT @@TRANCOUNT AS after_2_begin;
COMMIT TRAN;
SELECT @@TRANCOUNT AS after_1_commit;
BEGIN TRANSACTION;
SELECT @@TRANCOUNT AS after_3_begin;
ROLLBACK TRAN;
SELECT @@TRANCOUNT AS after_rollback;
基本的なもの:
エラー処理ポリシーを設定し、すべてのSQLステートメントでエラーをトラップします。
ストアドプロシージャのソースコード管理を使用するためのポリシーを決定します。
コメント付きのヘッダーをユーザー、日付/時刻、およびspの目的とともに含めます。
正常に実行された場合は明示的に0(成功)を返し、それ以外の場合は何かを返します。
重要な手順については、テストケース(1つまたは複数)と予想される結果の説明を含めます。
パフォーマンステストの習慣を身につけましょう。テキストの場合は、少なくとも実行時間を記録します。
明示的なトランザクションを理解して使用します。
SPからSPを呼び出すことはほとんどありません。再利用性は、SQLの別の球技です。