2014-03-26 82 views
2

我的應用程序使用返回整數的pl/pgsql函數。 返回的整數用作返回碼,以區分不同的錯誤。如何從plpgsql函數返回一個整數並回滾每個修改?

例如,如果插入數據的函數返回-1,則意味着已經存在一些數據,並且這被禁止再次嘗試插入相同的數據。但是,如果它返回-2,這意味着別的東西。這樣應用程序就知道錯誤並可以向用戶顯示有用的錯誤消息。

我現在的問題是,我希望在函數中的某些點上,當我檢測到錯誤時立即返回,並回滾到目前爲止在函數中完成的所有操作。如果我使用「引發異常」,它將回滾,但不返回一個整數。如果我使用「return -1;」,它將返回一個整數,但不會回滾修改。所以我堅持,因爲很明顯我不能這樣做既

這裏有一個假的例子功能:

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]我可以使用引發異常回滾,但當我這樣做時,我沒有返回的整數。

我可以設置在[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我的錯誤是,他們是五位數字而不是六位數字。編輯。 –

+1

ok,正確的語法是WHEN SQLSTATE'0U001'THEN。現在它工作了!但你爲什麼說這很奇怪?回滾很常見,但是獲取返回碼可能不常見?你怎麼知道爲什麼你的函數失敗,沒有返回碼? – user368507

相關問題