2016-08-29 8 views
1

私のHi/Loの実装では、排他テーブルロックを取得し、値を更新して1行を選択する関数が必要です。私は、次のコードを思い付いた:機能を呼び出すときにテーブルをロックし値を更新して行を返すPostgresql関数

CREATE OR REPLACE FUNCTION bb_next_hi(tbl varchar(35)) 
RETURNS setof record AS 
$$ 
    LOCK TABLE hilo IN ACCESS EXCLUSIVE MODE; 
    OPEN ref FOR SELECT hi as "Hi", lo as "Lo", "table" as "Table" FROM hilo WHERE "table" = $1; 
    UPDATE hilo SET hi = hi + 1 WHERE "table" = $1 
    RETURN ref; 

$$ LANGUAGE plpgsql; 

はしかし、それは「無名ポータル3」と同様の内容ではない行が、一つの列を返します。私は返されたref(以上)を繰り返す必要がありますね?

私が使用できるもう1つのアプローチは、UPDATE RETURNINGステートメントを使用することですが、この場合に競合状態が発生するかどうかはわかりません。どんな助けもありがとう。おかげ

+0

なぜ、単一の行だけをロックしたいのですか? –

+0

私は読者をロックする他の方法もないと思います。たぶん私は間違っていて何かを誤解していましたが、もしそうなら、いくつかの説明のためにはすばらしいでしょう:) – Davita

答えて

1

cursor変数を使用しています(宣言しておらず、他のPL/pgSQL必須要素もありません)。カーソル参照は実際には "ポータル"と呼ばれ、出力を説明します。より良いアプローチは次のとおりです。

CREATE OR REPLACE FUNCTION bb_next_hi(tbl varchar(35)) 
RETURNS TABLE ("Hi" int, "Lo" int, "Table" varchar(35)) AS $$ 
BEGIN 
    LOCK TABLE hilo IN ACCESS EXCLUSIVE MODE; 
    RETURN QUERY SELECT hi, lo, $1 FROM hilo WHERE "table" = $1; 
    UPDATE hilo SET hi = hi + 1 WHERE "table" = $1; 
    RETURN; 
END; 
$$ LANGUAGE plpgsql STRICT; 

本当に排他ロックが必要ですか?一貫性のあるテーブルスナップショットを取得するための侵入方法はずっと少なくなっています。

2

これは私にははるかに簡単なようだ:

CREATE OR REPLACE FUNCTION bb_next_hi(tbl varchar(35)) 
RETURNS setof record AS 
$$ 
BEGIN 
    LOCK TABLE hilo IN ACCESS EXCLUSIVE MODE; 
    RETURN QUERY UPDATE hilo SET hi = hi + 1 WHERE "table" = $1 
     RETURNING hi as "Hi", lo as "Lo", "table" as "Table"; 
END; 
$$ LANGUAGE plpgsql; 

、私はまた、通常RETURNS TABLE (col1 varchar, col2 varchar...)の代わりRETURNS setof record定義します。

+0

OPが得ようとしていたものとは異なり、これは "hi"の更新された値を返します。 – Patrick

+0

それは本当です、私はそれを考えなかった。 + = 1の場合、それは大きな問題ではありません。 –

関連する問題