2010-01-29 6 views
6

잠재적으로 실패 할 수있는 삽입 트리거에 일부 코드가 있습니다. 이러한 실패는 중요하지 않으며 이 아니고은 트랜잭션을 롤백해야합니다. 트리거 내에서 오류를 트랩하고 나머지 트랜잭션을 정상적으로 실행하려면 어떻게해야합니까?TSQL 트리거가 자동으로 실패 함

아래의 예는 내 뜻을 보여줍니다. 트리거는 의도적으로 원본 삽입 ("1")이 테이블에 삽입되지 않는 결과로 오류 조건을 만듭니다. Try/Catch는 트릭을 수행하지 않은 것 같습니다. 비슷하게 older stack overflow question은 "처음에 오류가 발생하는 것을 방지"하는 것 이외에는 답을 얻지 못했습니다. 항상 가능하거나 쉽지는 않습니다.

다른 아이디어?

create table test 
(
    a int not null 
); 
go 

create trigger testTrigger on test 
after insert as 
begin 
    insert into test select null; 
end; 
go 

insert into test values (1); 
+1

왜 시도 했는가?/캐치가 작동하지 않습니까? – cjk

+0

@ck : 트리거 내부의 제약 조건 위반으로 인해 트랜잭션이 파손되기 때문입니다. – Quassnoi

답변

2

트리거는 실패 할 수 없으며 트랜잭션 롤 포워드는 계속 수행 할 수 있습니다. 트리거가 실패하지 않도록 몇 가지 옵션이 있습니다.

1 - 당신은 후에이 제약을 체크하기위한 논리를 복제하고, 제약 조건을 위반하는 작업을 시도하지 않음으로써 실패하지 않도록 할 수 있습니다

INSERT INTO test WHERE val IS NOT NULL 

2 - 당신은 할 수 있습니다 대기열 디자인 패턴을 사용하여 잠재적으로 실패한 조치를 지연 시키십시오. 여기서 조치는 실패 할 수도 있고 실패하지 않을 수도 있습니다. 대기열 작성 작업이 실패하지 않을 수있는 테이블에 대기 행렬을 추가하여 대기열에 넣을 수 있습니다. 즉

INSERT INTO ACTION_QUEUE (action, parameters) VALUES ('INSERT INTO TEST', val) 
+0

이것이 유일한 길일 것 같네요. 그것은 어렵습니다. 아래 Quassnoi의 답변에 대한 내 의견을 참조하십시오. – BuschnicK

+0

@BuschnicK 트리거를 만드는 것은 시스템에서 할 수있는 더 침해적인 일 중 하나입니다. 이는 데이터베이스 동작을 적용하기위한 데이터베이스 스키마의 일부이며 다른 사용자의 데이터베이스에서이 작업을 수행합니다. 그들은 자리를 잡았지만 제대로 작동하는지 확신 할 수 없다면이 사용법이 적절하다고 생각하지 않습니다.솔직하게 트리거를 변경 사항을 전달하는 유일한 메커니즘으로 사용하는 경우 트리거가 자동으로 실패한 경우 변경 사항이 배송되지 않지만 트랜잭션이 완료 될 수 있으며 변경 데이터 "메시지"가 손실됩니다. 데이터를 안정적으로 다시 동기화 할 수 있습니까? –

+0

@BuschnicK 마지막 스냅 샷 이후 변경 사항을 비교하기 위해 일종의 변경 데이터 캡처 또는 다른 ETL 기술을 조사하는 것이 좋습니다. –

1

인해 트리거 SQL Server에서 구현되는 방식과, 트리거 내의 모든 제약 위반 트랜잭션 운명.

는이 일을하는 것과 같습니다

트리거 내부 XACT_ABORT을 해제 할 수있는 방법이 없다는 것을 제외하고는 운명 거래 결과
DROP TABLE test 

CREATE TABLE test 
(
     a INT NOT NULL 
) 

GO 

SET XACT_ABORT ON 
GO 

BEGIN TRANSACTION 

BEGIN TRY 
     INSERT 
     INTO test 
     SELECT NULL 
END TRY 
BEGIN CATCH 
     INSERT 
     INTO test 
     SELECT 1 
END CATCH 

.

SQL Server도 자율 트랜잭션이 부족합니다.

그 이유는 트리거가 아닌 저장 프로 시저에 모든 논리를 넣어야하는 또 다른 이유입니다.

+0

실제로 try..catch를 사용하지 않으면 운명의 거래가 없습니다. –

+0

@Alex : 확실히, 작업은 원자 적으로 취소됩니다. 이것은 단지 진행 상황을 보여주기위한 것이 었습니다. – Quassnoi

+0

저장 프로 시저가 어떻게 도움이됩니까? 트리거가 스토어드 프로 시저를 호출 할 것이라 생각하면 ... 여기에 도달하려고하는 배경 정보를 제공하려면 : 공급 업체에서 ERP 시스템을 제공하고에서 최신 데이터를 가져오고 싶습니다. 그것은 테이블입니다. 테이블에 트리거를 연결하고 데이터를 마사지하여 데이터베이스에 복사합니다. 우리는 원래의 ERP 시스템에서 문제를 일으킬 수 있기 때문에 우리의 방아쇠가 결코 실패하지 않을 것이라고 보장하려고합니다. – BuschnicK

0
  1. 당신은
  2. 당신은 트리거가 저장 프로 시저를 호출 할 수 있습니다 트리거 (사용주의) 내부 XACT_ABORT을 해제 할 수 있습니다. (지금 나는 정반대의 문제와 씨름하고있다 : 나는 트랜잭션을 중단 시키길 원하지만 논리는 트리거에서 호출 된 SP에 있고 트리거 자체는 아니기 때문에 이것은 발생하지 않는다.)
관련 문제