제약 조건으로 인해 DELETE가 실패하는지 테스트하는 방법이 있습니까?


10

실제로 삭제를 수행하지 않고 DELETE가 제약 조건 위반이 발생하는지 여부를 예측하고 싶습니다.

이 작업을 수행 할 수있는 옵션은 무엇입니까? DELETE의 "드라 이런"을 수행하는 간단한 방법이 있습니까?


이 명령문에 대한 예외를 막으려 고하거나이 삭제가 포함 된 더 큰 배치에서 오류 처리를 쉽게하려고합니까?
Aaron Bertrand

3
FK가 있는지 확인하고 SELECT 문을 실행하여 값을 확인할 수 있습니까?
SQLRockstar

Aaron : 별도의 트랜잭션에서 여러 개의 DELETE를 일괄 적으로 실행해야합니다. 하나가 실패하면 다른 하나는 이미 커밋 된 것입니다. (처음부터 나쁜 디자인이지만, 내 응용 프로그램이 아니며 변경되지 않습니다.) 현재 가장 좋은 해결 방법은 드라이 점검을 수행하여 DELETE가 실패하는지 확인하는 것처럼 들립니다.
Jay Sullivan

아직도 잘 모르겠습니다. 나머지 삭제를 성공 시키려고합니까, 아니면 모든 삭제가 성공할 것인지 미리 확인하려고합니까?
Aaron Bertrand

애런 : 죄송합니다. 확실하지는 않지만, 모두 성공할 수 있도록 노력하고 있습니다.
Jay Sullivan

답변:


24

모든 삭제가 모두 성공한 경우에만 모든 삭제를 처리하는 것이 목표라면 TRY / CATCH를 사용하지 마십시오.

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

하나 이상의 오류가 발생하더라도 성공적인 삭제를 모두 성공시키는 것이 목표라면 개별 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

한 가지 옵션은 트랜잭션을 시작하고 삭제를 실행 한 다음 항상 롤백하는 것입니다.

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
삭제가 성공하면 다시 실행 하시겠습니까? 삭제가 매우 비싸면 어떻게합니까? 삭제가 실패하면 어떻게 되나요? 한 번의 삭제와 두 번의 선택을 완료했습니다. 다음 삭제시 이동 여부를 어떻게 결정합니까?
Aaron Bertrand

1
이러한 요구 사항의 일부인 경우 처리해야합니다. 이 답변은 "간단한 '드라 이런'"에 관한 것입니다.
GaTechThomas

글쎄, 그들은 당신이 당신의 대답을 처음 제출했을 때가 아니었지만 지금 명확하게 밝혀졌습니다.
Aaron Bertrand

4
@GaTechThomas Aaron은 많은 기여를하기 때문에 가끔 짧지 만 그의 의도는 공격적이지 않을 것이라고 확신합니다. 나는 에서 이것을 논의 했고 당신과 함께 할 수있는 기회에 감사드립니다.
잭 topanswers.xyz 시도라고

1
@ JackDouglas 나는 당신이 요점을 참조하고 이해하는 힙 코멘트를 읽었습니다. 커뮤니티의 의견은 내가 그의 침략을 지적하기 위해 광대라고 불리는 부분을 제외하고는 합리적이었습니다. 나는 내가 공격적인 사람으로 보이는 사람을 이해하지 못합니다. 당시 제기 된 질문에 대한 합법적 인 답변을 게시했습니다. 생산 품질을 요구하지 않았으며 때로는 빠르고 쉽게 필요합니다. 그래서 대답에는 뾰족한 질문이 있습니다. 외모는 그가 내 대답을 거부하여 그의 선택을 받아 들였다. 이 실을 다른 곳으로 가져 가야합니까?
GaTechThomas

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.