2014-03-26 2 views
2

내 응용 프로그램에서는 정수를 반환하는 pl/pgsql 함수를 사용합니다. 반환 된 정수는 다른 오류를 구분하기 위해 반환 코드로 사용됩니다.plpgsql 함수에서 정수를 반환하고 모든 수정 사항을 롤백하는 방법은 무엇입니까?

예를 들어, 데이터를 삽입하는 함수가 -1을 반환하면 이는 이미 존재하는 데이터이며 이미 동일한 데이터를 다시 삽입하는 것을 금지한다는 것을 의미합니다. 그러나 -2를 반환하면 다른 것을 의미합니다. 그런 식으로 응용 프로그램은 오류를 알고 사용자에게 유용한 오류 메시지를 표시 할 수 있습니다.

내 문제는 이제 내가 함수의 일부 지점에서 즉시 오류를 감지하고 함수에서 지금까지 수행 된 모든 것을 롤백하려고합니다. "raise 예외"를 사용하면 롤백되지만 정수는 반환되지 않습니다. "return -1;"을 사용하면 정수가 반환되지만 롤백 수정은 반환되지 않습니다. [1] [2] 내가 롤백 인상 예외를 사용할 수 있습니다에서

CREATE OR REPLACE FUNCTION create_flight_and_passengers(
    _date timetamp, 
    _name text, 
    _passengers integer[] 
) 
RETURNS integer 
LANGUAGE plpgsql 
AS $$ 
DECLARE 
    return_code integer; 
BEGIN 
    INSERT INTO flights 
    VALUES (_name); 

    SELECT function_1(_date, _passengers) into return_code; 
    if (return_code = -1) then 
     -- [1] rollback everything done since beginning of function 
     -- create_flight_and_passengers() and return -1 
    end if; 

    SELECT function_2(_date, _passengers) into return_code; 
    if (return_code = -1) then 
     -- [2] rollback everything done since beginning of function 
     -- create_flight_and_passengers() and return -2 
    end if; 

    return 0; 
END; 
$$; 

:하지만, 그래서 나는 분명히 내가 두

을 할 수 없기 때문에 여기에 가짜 예를 들어, 함수의, 붙어 내가 이렇게 할 때 반환 된 정수가 없습니다.

로컬 변수를 [1]과 [2]로 설정하면 예외가 발생하고 EXCEPTION에서는이 변수를 테스트하여 예외의 출처를 알 수 있습니다. 더 잘!

난 당신이 전화 한 당신은 함수의 효과를 롤백 할 수 있습니다 모르겠어요 및 그 (function_2() 내 예제에서 function_1() 등)

어떤 아이디어를 종료했다?

답변

2

이것은 매우 기괴한 일입니다. 당신이 정말로 필요로하는 경우에, 당신은 이런 식으로 할 수 있습니다 : 여기

DECLARE 
    retval integer; 
BEGIN 
    retval := 0; 
    BEGIN 
    ... make my changes ... 
    IF (... is something wrong? ...) THEN 
     RAISE EXCEPTION SQLSTATE '0U001'; 
    END IF; 
    EXCEPTION 
    WHEN '0U001' THEN 
     retval := -1; 
    END; 
END; 

개념은 BEGIN ... EXCEPTION 블록이 서브 트랜잭션을 정의하는 것입니다. 블록 내의 RAISE EXCEPTION은 서브 트랜잭션을 롤백합니다. 우리는 외부 수준에서이를 잡아 예외가 함수 외부로 전파되지 않도록하고 전체 트랜잭션을 중단합니다.

the PL/PgSQL documentation을 참조하십시오.

+0

오류 : '0U0001'또는 그 근처의 SQLSTATE 코드가 잘못되었습니다. 0U0001이 오류 코드에 없습니다 (http://www.postgresql.org/docs/9.1/static/errcodes-appendix.html). "사용자 정의"오류 코드를 어떻게 활성화합니까? – user368507

+0

@ user368507 실수는 6이 아닌 5 자리수입니다. 편집 됨. –

+1

이고 올바른 구문은 WHEN SQLSTATE '0U001'THEN입니다. 이제 작동 중입니다! 그런데 왜 그렇게 기괴하다고 말하는가? 롤백은 일반적이지만 리턴 코드를 얻는 것이 일반적이 아닙니다. 반환 코드없이 함수가 실패한 이유를 어떻게 알 수 있습니까? – user368507

관련 문제