2012-11-27 2 views
0

테이블에 데이터를 삽입하려고하면 고유 키 위반 또는 외부 키 위반과 같은 여러 가지 이유로 실패 할 수 있습니다.오라클 - 예외 또는 트리거를 사용해야합니까?

고유 키가 위반되었음을 알기 위해 DUP_VAL_ON_INDEX 예외를 사용할 수 있지만 고유 한 키가 여러 개인 열이있는 경우 어떻게 알 수 있습니까? 이 경우 트리거를 사용해야합니까?

(I 괜찮 확인 데이터가 삽입 될 수 있도록 대신 테이블을 쿼리의 저장 프로 시저의 흐름을 구동하기 위해 예외를한다 사용하고 있습니다.)

답변

0

(제약에서) 예외 또는 트리거를? 나는 둘 다 말하지 않는다.

강력하게은 응용 프로그램 코드와 쿼리를 사용하여 트리거 및 제약 조건과 달리 응용 프로그램의 논리를 사용하는 것이 좋습니다. 논리를 오류 조건 처리와 분리하면 코드의 동작이 더 마술처럼 보일뿐입니다.

제약 조건은 백업 계획 (응용 프로그램 논리 오류 또는 변경의 경우)으로 매우 유용하지만 사용자가 원하는 방식으로 런타임 오류 처리를 지원하지 않는다는 점에서 옳습니다 (즉, 노출하는 데 도움이되지 않음) INSERT 문이 사용하려고했던 중복 키).

의심의 여지가 없으므로 트리거를 사용하여 설명하는 것을 매우 쉽게 수행 할 수 있지만 궁극적으로는 동일한 논리적 테스트 ("이 레코드가 이미 존재합니까?")를 단순히 숨기고 있다는 것입니다. 트리거에서 응용 프로그램 코드 (예 : INSERT 문이 존재하는 곳)와 반대입니다. 테이블에 여러 개의 트리거가있는 경우 도 불필요하게 실행하는 오버 헤드를 거치게됩니다. 처음에는 오류가 발생하고 다른 하나는 아무 효과가 없었을 것입니다.

당신은 추가적인 문을 작성하지 않으려면 미리 확인 새 INSERT 문을 실행하기 전에 데이터의 상태를, 나는이 같은 것을 사용하는 것이 좋습니다 것입니다 : 적어도 다음

INSERT INTO my_table (col1, col2) 
    SELECT l_val1, l_val2 
    FROM dual 
    WHERE NOT EXISTS (
    SELECT 1 
    FROM my_table t 
    WHERE t.col1 = l_val1 
    AND t.col2 = l_val2 
) 

을하면됩니다 키를 위반하지는 않지만 SQL%ROWCOUNT이 0 (삽입 된 행이 없으므로 이미 존재해야 함)인지 또는 1을 테스트하여 행이 이미 있는지 여부를 알 수 있습니다.

그러나 여전히 키 위반을 제공하지는 않습니다 값. 어떤 제약 조건을 위반하는지 알아 내려면 쿼리를 작성해야합니다.

+0

삽입 문은 여전히 ​​어떤 열의 복제가 발생했는지 알려주지 않습니다. – user1831003

+0

아니, 그건 사실이야. 당신은 그것을 다시 질문해야 할 것입니다. – Ben

0

이것은 트리거가 아닌 것입니다. can not query the target table inside a trigger을 기억하십시오. 따라서 고유성 위반 여부를 실제로 확인할 수는 없습니다. 트리거를위한 ​​가장 좋은 이유는 시퀀스의 ID와 같은 행에 기본 데이터가 채워져 있는지 확인하는 것입니다. 또한 삽입 된 행이 귀하의 진술과 다른 이유가 명확하지 않기 때문에 트리거는 코드를 난독 화합니다.

제약 조건은 명백한 것 이외의 유용한 기능을 수행합니다. 옵티마이 저는 제약 조건의 정보를 사용하여 실행 계획을 판단 할 수 있습니다. 예를 들어 옵티마이 저가 컬럼이 NOT NULL인지 여부를 아는 경우보다 효율적인 라우트를 계산할 수 있습니다.그것은 가치가 무엇인지에 대한

BEGIN 
    ... application code ... 
    BEGIN 
     INSERT INTO mytable (col1, col2) VALUES (val1, val2); 
    EXCEPTION WHEN DUP_VAL_ON_INDEX THEN 
     ... error handling code ... 
    END; 
    ... application continues... 
END; 
+0

트리거를 지적 해 주셔서 감사합니다. 그러나, 내가 이것을 알아야합니다 : 위의 코드를 사용하는 경우 예외가 발생한 고유 한 열을 어떻게 알 수 있습니까? – user1831003

+0

자동으로 알릴 방법이 없다고 생각합니다. 기존의 일치하는 키를 찾기 위해서는 아마도'SELECT'을해야 할 것입니다. 나는 대부분의 경우 그것이 중요하지 않다고 말할 것이다. – eaolson

0

, 난 당신이 하지 전적으로 의존 할 것을 제안 : @ 벤에 의해 주어진

INSERT 문은 위의 당신은 또한 익명의 블록 내부에 문을 포장 할 수있는 좋은 하나입니다 고유성을 적용하는 애플리케이션 코드. 하나의 핵심 (의도적 인 말장난) 이유는 특히 데이터가 여러 트랜잭션에서 동시에 삽입되거나 업데이트되는 경우에이를 올바르게 수행하는 코드를 작성하기 어렵다는 것입니다. 데이터베이스가 정확하고 효율적으로 시행 할 고유 한 제약 조건을 선언하는 것은 비교적 간단합니다.

당신이 알고 싶은 경우에 어떤 고유 제한 한 접근 방식을 위반 한 (그리고 나는 그것을하지 "꽤"의 실현)이다 한열 : 대한 (

  1. 오류 메시지에서 제한 조건 이름을 구문 분석 예 : SQLERRM으로 반환).
  2. 데이터 딕셔너리 나 자신의 테이블과 같은 일부 메커니즘을 사용하여 제약 조건에 해당하는 열을 "조회"하십시오.

고유 한 제약 조건을 위반 한행, 당신은 this example에 설명 된대로 오류 로그 테이블에 잘못된 행을 기록하는 INSERT 문의 LOG ERRORS INTO 절을 사용할 수있는 알고 싶다면.

당신이 행 열이 고유 제한 조건을 위반하는 알고 싶다면, 당신은 두 가지 방법을 결합 할 수 있습니다 - 당신이 LOG ERRORS INTO 절을 사용하여 행을 기록하고 있습니다 (오류 메시지에서 constaint 이름을 구문 분석하는 또한 오류 로깅 테이블에 기록됩니다) 해당하는 열을 찾습니다.

그렇다고해서 반드시 다음 중 하나를 선택할 필요는 없습니다. a) 데이터를 먼저 확인하고 검사를 통과하면 삽입하는 것, b) 데이터를 삽입 한 다음보고 및/또는 연기 어떤 오류든지.