パーティションテーブルでのUPDATE~WHERE CURRENT OF カーソル時にFOR UPDATE/SHARE参照無しエラー

実現したいこと

前提

PostgreSQL16で以下のストアドを実行しています。
以下のエラーメッセージが表示されてしまい、対処に困っています。

発生している問題・エラーメッセージ

エラー: カーソル"<unnamed portal 32>"にはテーブル"test_2"への FOR UPDATE/SHARE参照がありません CONTEXT: SQL文 "UPDATE test SET memo = 'updated:'||now() WHERE CURRENT OF cur" PL/pgSQL関数inline_code_blockの20行目 - SQL ステートメント ERROR: カーソル"<unnamed portal 32>"にはテーブル"test_2"への FOR UPDATE/SHARE参照がありません SQL 状態: 24000

該当のソースコード

--テストデータ生成 drop table if exists test; CREATE TABLE test (id int, logdate date, memo text) PARTITION BY LIST (id); --CREATE TABLE test (id int, logdate date, memo text) PARTITION BY LIST (logdate); CREATE TABLE test_1 PARTITION OF test FOR VALUES in ('1'); CREATE TABLE test_2 PARTITION OF test FOR VALUES in ('2'); CREATE TABLE test_3 PARTITION OF test FOR VALUES in ('3'); --CREATE TABLE test_2016 PARTITION OF test FOR VALUES in ('2016-12-31'); --CREATE TABLE test_2017 PARTITION OF test FOR VALUES in ('2017-12-31'); --CREATE TABLE test_2018 PARTITION OF test FOR VALUES in ('2018-12-31'); ALTER TABLE test ADD PRIMARY KEY (id, logdate); -- データの挿入 INSERT INTO test VALUES (1, '2016-12-31', 'memo11'); INSERT INTO test VALUES (1, '2017-12-31', 'memo12'); INSERT INTO test VALUES (2, '2017-12-31', 'memo21'); INSERT INTO test VALUES (2, '2018-12-31', 'memo22'); INSERT INTO test VALUES (3, '2018-12-31', 'memo31'); INSERT INTO test VALUES (3, '2016-12-31', 'memo32');
--PL/pgSQLでのカーソル動作 DO $$ DECLARE cur CURSOR(arg_id test.id%TYPE,arg_logdate test.logdate%TYPE) FOR SELECT * FROM test where id = arg_id and logdate = arg_logdate FOR UPDATE OF test NOWAIT; rec test%ROWTYPE; BEGIN OPEN cur( '1' ,'2017-12-31' as date ); LOOP FETCH cur INTO rec; EXIT WHEN NOT FOUND; -- パーティションキーの値を変更しない UPDATE test SET memo = 'updated:'||now() WHERE CURRENT OF cur; END LOOP; CLOSE cur; END; $$;

試したこと

  • リストパーティションキーをlogdateのみ、カーソル条件をidのみでは更新できる

パーティションテーブルを変更
CREATE TABLE test (id int, logdate date, memo text) PARTITION BY LIST (logdate);
以下のようにカーソルの条件をidのみとした場合は正常に更新できた
cur CURSOR(arg_id test.id%TYPE,arg_logdate test.logdate%TYPE)
FOR
SELECT * FROM test
where
id = arg_id
-- and logdate = arg_logdate
FOR UPDATE OF test NOWAIT;

  • UPDATE時の条件をCURRENT OF カーソルではなく、主キーを指定すれば更新できる
    id = rec.id and logdate = rec.logdate;

補足情報(FW/ツールのバージョンなど)

PostgreSQL15でも結果は変わらないです。
パーティションテーブルへの変更を行っている中で対処に困っています。
ソースコードの修正を少なくできるならしたいと考えています。

コメントを投稿

0 コメント