2017-03-07 28 views
1

私はPostgreSQLの関数の中でセーブポイント機能を使いたいです。私は、セーブポイントをPostgresの関数の中で使うことはできないと読んでいます。PostgreSQL関数のセーブポイント

私はロールバックしている間に、セーブポイントを使用したい特定のポイントにロールバックする必要があります。それを行う別の方法は何ですか?

サンプルコード

CREATE or replace FUNCTION fn_loadData_Subha() 
RETURNS BIGINT 
AS 
$$ 
DECLARE 
    batchId BIGINT; 
    currentTime TIMESTAMP; 
    processName VARCHAR(20); 
BEGIN 


-- Getting current date and time 
select TIMESTAMP 'NOW' into currentTime; 
select 'ETL_Subha' INTO processName; 

SAVEPOINT first_savepoint; 
-- Inserting new record into batch log table 
INSERT INTO TB_HSS_BATCH_LOG 
(PROCESS_NAME,START_DATE,STATUS) 
SELECT processName,currentTime,'STARTED'; 

select currval('TB_HSS_BATCH_LOG_id_seq') INTO batchId; 

-- Inserting cost data to history table 
    Insert into tb_hss_procedure_cost_hist1 
    (HOSP_SYSTEM, HOSP_FACILITY, surgeon_name, procedure_name, department, current_dept_rank, no_of_surgeons, current_imp_cost 
    , current_med_surg_cost, current_total_cost, annual_volume, sys_pref_cost,load_seq_no, CREATED_AT) 
    Select 
    HOSP_SYSTEM, HOSP_FACILITY,surgeon_name,procedure_name,department,current_dept_rank, no_of_surgeons, current_imp_cost 
    , current_med_surg_cost, current_total_cost, annual_volume, sys_pref_cost, batchId,currentTime 
    from tb_hss_procedure_cost_stag_in; 

RELEASE SAVEPOINT first_savepoint;  
RETURN 1; 


EXCEPTION 
WHEN PLPGSQL_ERROR THEN 
    RAISE EXCEPTION '% %', SQLERRM, SQLSTATE; 
    RAISE NOTICE '% %', SQLERRM, SQLSTATE; 
    RETURN 0; 
WHEN OTHERS THEN 
    RAISE EXCEPTION '% %', SQLERRM, SQLSTATE; 
    RAISE NOTICE '% %', SQLERRM, SQLSTATE; 
    RETURN 0; 
    ROLLBACK TRANSACTION; 

END; 
$$LANGUAGE plpgsql; 
+0

あなたは 'first_savepoint'へのロールバックが必要になります。https://www.postgresql.org/docs/current/static/sql-rollback-to.html –

+0

あなたは、PostgreSQLの関数内の任意のトランザクション関連のSQL文を使用することはできません。 –

+0

savepointは関数内では使用できないため、first_savepointへのロールバックは関数内では機能しません。私はセーブポイントの代替を知りたいです。 –

答えて

2

PL/pgSQL関数でセーブポイントを使用する方法はBEGIN ... EXCEPTION ... ENDブロックを使用することです。これにより、セーブポイントがBEGINに設定され、例外が発生したときにロールバックされます。

だからあなたのコードは、(私が正しくあなたのコードを読んでいる場合は100%わからない)というようになります。

DECLARE 
    batchid bigint; 
    processname varchar(20) := 'ETL_Subha'; 
BEGIN 
    BEGIN 
     INSERT INTO TB_HSS_BATCH_LOG 
     (PROCESS_NAME,START_DATE,STATUS) 
     VALUES (processname,current_timestamp,'STARTED') 
     RETURNING id INTO batchid; 
     RETURN 1; 
    EXCEPTION 
     WHEN OTHERS THEN 
     RETURN 0; 
    END; 
END; 

あなたのコードにいくつかの一般的な注意事項:

  • batchidを決してありません中古。
  • currenttimeは不要です– current_timeを呼び出すたびに、トランザクション内で同じ値が返されます。
  • RAISEで例外を発生させると、実行が終了します。エラーをスローしたい場合は、元の例外をキャッチしないでください。それはあなたの例外よりも意味があります。上のコードでは、例外をキャッチしたい代わりに0を返すことを前提としています。
  • SELECT val INTO variableはフードの下でvariable := valueと同じですが、後者は一般的にはより読みやすいと考えられます。
+0

ありがとうLaurenz ..コードは部分的なコードです。実際には後で使用されるいくつかの未使用のものがあります。 –

+0

いいえ、私は0に戻したくありません、私は特定のポイント(Savepointの代わりにSavepointの代わりに関数内で使用することはできません)をロールバックしたいのですが...それは私がこの質問を投稿した理由の最も重要です.. –

+0

すぐに 'EXCEPTION'ブロックに入ると、セーブポイントにロールバックされます。 –