制約が原因でDELETEが失敗するかどうかをテストする方法はありますか?


10

実際に削除を実行せずに、DELETEが制約違反に遭遇するかどうかを予測できるようにしたいと思います。

これを行うための私のオプションは何ですか?DELETEの「ドライラン」を実行する簡単な方法はありますか?


このステートメントだけの例外を回避しようとしていますか、それとも、この削除を含む大きなバッチでのエラー処理を容易にしようとしていますか?
アーロンバートランド

3
FKが存在するかどうかを確認し、SELECTステートメントを実行して値を確認できますか?
SQLRockstar 2012

Aaron:複数のDELETEのバッチを個別のトランザクションで実行する必要があります。1つが失敗した場合、他はすでにコミットされています。(最初から悪い設計だと思いますが、それは私のアプリケーションではなく、変更されていません。)現時点での最善の回避策は、DELETEが失敗するかどうかを確認するためのドライチェックを行うようなものです。
ジェイ・サリバン

まだわかりません。残りの削除を成功させようとしていますか、それともすべての削除が成功するか、またはどれも成功しないことを前もって確認しようとしていますか?
アーロンバートランド

アーロン:すみません、はっきりさせていませんが、はい、すべてが成功するか、どれも成功しないようにしています。
ジェイサリバン

回答:


24

すべての削除が成功した場合にのみすべての削除を処理することが目標である場合は、TRY / CATCHを使用しないでください。

BEGIN TRANSACTION;
BEGIN TRY
  DELETE #1;
  DELETE #2;
  DELETE #3;
  COMMIT TRANSACTION;
END TRY
BEGIN CATCH
  ROLLBACK TRANSACTION;
END CATCH

1つ以上が失敗してもすべての成功した削除を成功させることを目標とする場合は、個別のTRY / CATCHを使用できます。

BEGIN TRY
  DELETE #1;
END TRY
BEGIN CATCH
  PRINT 1;
END CATCH

BEGIN TRY
  DELETE #2;
END TRY
BEGIN CATCH
  PRINT 1;
END CATCH

6

1つのオプションは、トランザクションを開始し、削除を実行してから、常にロールバックすることです。

begin tran

delete Table1 where col1 = 1

-- Test whether it is there
select * from Table1 where col1 = 1

rollback tran

-- Confirm that it is still there
select * from Table1 where col1 = 1

1
削除が成功した場合は、もう一度実行しますか?削除に非常に費用がかかる場合はどうなりますか?そして、削除が失敗した場合、どうしますか?1つの削除と2つの選択を実行しました。次の削除に進むかどうかはどうすればよいですか?
アーロンバートランド

1
それらが要件の一部である場合は、処理する必要があります。この回答は、「単純な「ドライラン」」に関するものです。
GaTechThomas 2012

まあ、あなたが最初に回答を提出したときではありませんでしたが、現在は明確になっています。
アーロンバートランド

4
@GaTechThomasアーロンは多くの貢献をしているので、彼は時々簡潔ですが、彼の意図は積極的ではなかったと確信しています。これについてはThe Heapで説明しましたが、皆さんと一緒にそうする機会にも感謝します。
ジャックはtopanswers.xyzを2012

1
@JackDouglas私はあなたがポイントを参照して理解するヒープのコメントを読みました。コミュニティのコメントは、私が彼の攻撃を指摘したためにピエロと呼ばれた部分を除いて、合理的でした。自分がアグレッシブであると見なされていたのは、私がどういう人なのかわかりません。当時提示された質問に対する正当な回答を投稿しました。それは生産品質を要求しませんでした-時には、あなたは迅速かつ簡単に必要なだけです。だから私の答えでは、先のとがった質問が出ます。彼が選ばれるように、彼は私の答えを否定しているように見えました。このスレッドを別の場所に移動する必要がありますか?
GaTechThomas 2012

0

Aaron Bertrandが提供するソリューションをいくつかのコードで改善したいと思います。テーブルの要素を追加したり、例外を管理して失敗を無視したり、エラーの後にプロセスを停止したりする場合です。

これはテーブルからレコードを選択し、例外なくそれらを削除しようとします:

DECLARE @MaxErrors INT
SET @MaxErrors = 5;    // Setting 0 will stop process after the first error!

SELECT
    [Id]
    , ROW_NUMBER() OVER (ORDER BY Id ASC) AS [Index]
INTO #DeletingItems
FROM myTable

DECLARE @Current INT, @Max INT, @Id INT, @TotErrors INT
SELECT
    @Current = 1
    , @TotErrors = 0
    , @Max = MAX([Index])
FROM #DeletingTable

WHILE @Current <= @Max
BEGIN
    SELECT
        @Id = [Id]
    FROM #DeletingItems
    WHERE
        [Index] = @Index;

    BEGIN TRANSACTION;    
    BEGIN TRY    
        DELETE FROM myTable WHERE [Id] = @Id;

        COMMIT TRANSACTION;    
    END TRY    
    BEGIN CATCH    
        ROLLBACK TRANSACTION;

        SET @TotErrors = @TotErrors + 1;

        IF @TotErrors > @MaxErrors
            BREAK;
    END CATCH

    SET @Current = @Current + 1;
END

1
どうして?これは、受け入れられた回答をどのように改善したのですか?
ToolmakerSteve 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.