(注:以下の採用された回答で更新されました。)
PostgreSQL 8.1 (またはそれ以降) のパーティション テーブルの場合、パーティションの分離を定義する制約付きフィールドへの変更を意味するUPDATE
場合、あるパーティションから別のパーティションにレコードを「移動」するためのトリガーと手順をどのように定義しますか?UPDATE
たとえば、次のようにアクティブなレコードと非アクティブなレコードに分割されたテーブル レコードがあります。
create table RECORDS (RECORD varchar(64) not null, ACTIVE boolean default true);
create table ACTIVE_RECORDS ( check (ACTIVE) ) inherits RECORDS;
create table INACTIVE_RECORDS ( check (not ACTIVE) ) inherits RECORDS;
トリガーと関数はINSERT
うまく機能します。新しいアクティブなレコードが 1 つのテーブルに配置され、新しい非アクティブなレコードが別のテーブルに配置されます。UPDATE
ある子孫テーブルから別の子孫テーブルにレコードを「移動」するために ACTIVE フィールドに s を入力したいのですが、これができない可能性があることを示唆するエラーが発生しています。
トリガーの仕様とエラー メッセージ:
pg=> CREATE OR REPLACE FUNCTION record_update()
RETURNS TRIGGER AS $$
BEGIN
IF (NEW.active = OLD.active) THEN
RETURN NEW;
ELSIF (NEW.active) THEN
INSERT INTO active_records VALUES (NEW.*);
DELETE FROM inactive_records WHERE record = NEW.record;
ELSE
INSERT INTO inactive_records VALUES (NEW.*);
DELETE FROM active_records WHERE record = NEW.record;
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
pg=> CREATE TRIGGER record_update_trigger
BEFORE UPDATE ON records
FOR EACH ROW EXECUTE PROCEDURE record_update();
pg=> select * from RECORDS;
record | active
--------+--------
foo | t -- 'foo' record actually in table ACTIVE_RECORDS
bar | f -- 'bar' record actually in table INACTIVE_RECORDS
(2 rows)
pg=> update RECORDS set ACTIVE = false where RECORD = 'foo';
ERROR: new row for relation "active_records" violates check constraint "active_records_active_check"
トリガー プロシージャ (NULL を返すなど) をいじると、トリガーが呼び出される前に制約がチェックされ、エラーが発生したことがわかります。これは、現在のアプローチが機能しないことを意味します。これを機能させることはできますか?
更新/回答
以下は、UPDATE
私が最終的に使用したトリガー手順であり、各パーティションに割り当てられた同じ手順です。クレジットは完全にBellにあり、その答えは、パーティションでトリガーするための重要な洞察を私に与えてくれました:
CREATE OR REPLACE FUNCTION record_update()
RETURNS TRIGGER AS $$
BEGIN
IF ( (TG_TABLE_NAME = 'active_records' AND NOT NEW.active)
OR
(TG_TABLE_NAME = 'inactive_records' AND NEW.active) ) THEN
DELETE FROM records WHERE record = NEW.record;
INSERT INTO records VALUES (NEW.*);
RETURN NULL;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;