私はPL/pgSQLの初心者です... Postgres 9.5.0を使用しており、新しいレコードが挿入されるたびに列を更新する必要があります。列には、area_pol
およびarea_ofi
に入力された値を入力する必要があります。
私のケースに合うようにこの関数を作成しようとしています:
CREATE OR REPLACE FUNCTION sch_cap.fc_atualiza_dif_area()
RETURNS trigger AS
$$
BEGIN
UPDATE
sch_cap.tbl_cap
SET
dif_area = abs(100 - (tbl_cap.area_pol / (tbl_cap.area_ofi * 100)));
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER tg_atualiza_dif_area
BEFORE INSERT OR UPDATE ON sch_cap.tbl_cap
FOR EACH ROW EXECUTE PROCEDURE sch_cap.fc_atualiza_dif_area();
しかし、レコードを挿入しようとすると、次のエラーが表示されます。
エラー:スタックの深さの制限を超えました
ヒント:プラットフォームのスタック深度制限が適切であることを確認した後、構成パラメーター "max_stack_depth"(現在は2048kB)を増やします。
それを正しくする方法は?
新しいレコードが挿入されるたびに列を更新する必要がある
説明がトリガー定義とBEFORE INSERT OR UPDATE
と矛盾しています。単にBEFORE INSERT
か、説明が間違っています。
次に、トリガー関数全体が誤解されています。ちょうどでしょう:
CREATE OR REPLACE FUNCTION sch_cap.fc_atualiza_dif_area()
RETURNS trigger AS
$func$
BEGIN
NEW.dif_area := abs(100 - (NEW.area_pol / (NEW.area_ofi * 100)));
END
$func$ LANGUAGE plpgsql;
行が挿入される前に、必要な値assignを指定するだけです。 (ここにSET
はありません。)
しかし、実際には、私は VIEW
Evanの提案 を使用します。
あなたのコメント に関しては、QGISが 更新可能なビューの自動機能に何らかの影響を与える場合 (あなたが gis.SEの関連する質問)で述べたように )、テーブルにwritingを直接保持します。 VIEW
は、この場合のみの表現であり、機能的に依存する追加の列を表示します。
これはトリガーの動作方法ではありません。更新の前にTRIGGER
を実行する必要があります。その後、NEWレコードで SET
を使用します。
SET new.dif_area = abs(100 - (OLD.area_pol / (OLD.area_ofi * 100)));
しかし、さらに良いのは、これを完全に削除してVIEW
を使用することです。
CREATE VIEW sch_cap.tbl_cap AS
SELECT *, abs(100 - (area_pol / (area_ofi * 100))) AS dif_area
FROM tbl_cap;
トリガーコードは、テーブルtbl_cap
の行が更新されるたびに実行されます。
トリガーがtbl_cap
のすべての行を更新します(または、挿入または更新された行だけかもしれません-PostgreSQLの内部や他のいくつかのDBMSがわかりません)。
したがって、トリガーを実行すると、テーブルの行が変更されます。これにより、トリガーが実行されます。これはテーブルの行を変更します。これにより、トリガーが実行されます。これはテーブルの行を変更します。これにより、トリガーが実行されます。これにより、テーブルの行が変更されます。これは、スタック(トリガーの新しい反復に飛び込む前に環境の現在の値を追跡する)がいっぱいになるまで繰り返されます。それはあなたが見たエラーです。この無限再帰の結果、トリガー自体がトリガーされます。
Evan Carroll's answer に記載されているように、new
およびold
"tables"を使用して、元の更新または挿入がテーブルに書き込む内容を変更して、 2回目の更新、つまり無限ループ。