新しい行を挿入または更新する前に、配列フィールドのネストを解除するPostgresトリガーを記述しようとしています。例えば。
SELECT
unnest(something)
FROM NEW
ただし、これによりエラーが発生するようです。
「新しい」関係は存在しません
トリガー関数の中でNEW行を使用して、配列フィールドのネストを解除してさらに処理できるようにするにはどうすればよいですか?
CREATE TABLEステートメント
以下は、テーブル構造の例です。
CREATE TABLE parent_table (
id uuid NOT NULL,
jsonb_array_field jsonb[] NOT NULL DEFAULT '{}'::jsonb[],
CONSTRAINT "parent_table_pkey" PRIMARY KEY (id),
);
CREATE TABLE many_to_one_table (
id serial primary key,
parent_table_id uuid references parent_table(id),
subfield_a text,
subfield_a text
);
TRIGGER関数
TRIGGER関数の本質は次のとおりです。
CREATE OR REPLACE FUNCTION unnest_and_normalize_json() RETURNS TRIGGER AS
$body$
begin
if NEW.jsonb_array_field is null then
raise exception 'jsonb_array_field is null';
else
insert into
many_to_one_table(subfield_a, subfield_b)
select
parent_table_id, -- this is to be the ForeignKey
json_data->>'subfieldA' as subfield_a,
json_data->>'subfieldB' as subfield_b
from (
select
id, -- need ID for ForeignKey relationship
unnest(jsonb_array_field) as json_data
from new
) as unnested_json;
end if;
RETURN new;
end;
$body$
LANGUAGE plpgsql;
TRIGGERステートメント
トリガーステートメントは、データが「移行」テーブルにミラーリングされている限り、INSERTおよびUPDATEの前または後に実行できます。
CREATE TRIGGER unnest_and_normalize_json_on_insert AFTER INSERT ON parent_table
FOR EACH ROW EXECUTE PROCEDURE unnest_and_normalize_json();
CREATE TRIGGER unnest_and_normalize_json_on_update AFTER UPDATE ON parent_table
FOR EACH ROW EXECUTE PROCEDURE unnest_and_normalize_json();
ForeignKey clarificationデータモデルのこの部分を移行して、JSONフィールドではなくForeignKey関係を使用しようとしています。トリガーは、normalized_table
には今後のデータがありますが、古いレコードからデータをバックフィル/移行します。
NEW
およびOLD
トリガー関数はrecords-それぞれ該当する場合にのみ定義されます。 (たとえば、OLD
トリガーにはINSERT
はありません。) ROW
operations を実行できます。ネストされた列は、FROM
リストに含まれているテーブルと同様に、ドット表記(テーブル修飾列名など)で参照します。 NEW
とOLD
は、トリガー関数のSQL DMLステートメントのほぼすべての場所に表示されます。 (EXECUTE
を使用した動的SQLを除く。)
NEW
を実際のテーブルとして扱うには、まず変換する必要があります-これは通常は不要です。例:(SELECT NEW.*)
。意味のあるユースケースについては、この関連回答の章3。を参照してください。
基本的なトリガー機能は次のように燃え尽きます:
CREATE OR REPLACE FUNCTION unnest_and_normalize_json()
RETURNS trigger AS
$func$
BEGIN
INSERT INTO many_to_one_table (parent_table_id, subfield_a, subfield_b)
SELECT NEW.id
, ja->>'subfieldA' AS subfield_a -- column alias only for documentation
, ja->>'subfieldB'
FROM unnest(NEW.jsonb_array_field) ja; -- produces a derived table
RETURN NEW; -- optional for AFTER trigger
END
$func$ LANGUAGE plpgsql;
これは単なるノイズでした:
if NEW.jsonb_array_field is null then ...
列jsonb_array_field
は次のように定義されます。
jsonb_array_field jsonb[] NOT NULL DEFAULT '{}'::jsonb[],
これはAFTER
トリガーです。NOT NULL
制約は、この時点でjsonb_array_field
のNULL
の例外をすでに発生させています。
2つのトリガーを1つにマージできます。
CREATE TRIGGER unnest_and_normalize_json_on_insert
AFTER INSERT OR UPDATE ON parent_table -- !
FOR EACH ROW EXECUTE PROCEDURE unnest_and_normalize_json();
とはいえ、UPDATE
とDELETE
を適切にカバーするには、さらに多くのことを行う必要があります。これと同じ(章The dark side):