web-dev-qa-db-ja.com

列を更新するトリガー関数

私は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)を増やします。

それを正しくする方法は?

4
Felipe Almeida

新しいレコードが挿入されるたびに列を更新する必要がある

説明がトリガー定義と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は、この場合のみの表現であり、機能的に依存する追加の列を表示します。

2

これはトリガーの動作方法ではありません。更新の前に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;
5
Evan Carroll

トリガーコードは、テーブルtbl_capの行が更新されるたびに実行されます。

トリガーがtbl_capのすべての行を更新します(または、挿入または更新された行だけかもしれません-PostgreSQLの内部や他のいくつかのDBMSがわかりません)。

したがって、トリガーを実行すると、テーブルの行が変更されます。これにより、トリガーが実行されます。これはテーブルの行を変更します。これにより、トリガーが実行されます。これはテーブルの行を変更します。これにより、トリガーが実行されます。これにより、テーブルの行が変更されます。これは、スタック(トリガーの新しい反復に飛び込む前に環境の現在の値を追跡する)がいっぱいになるまで繰り返されます。それはあなたが見たエラーです。この無限再帰の結果、トリガー自体がトリガーされます。

Evan Carroll's answer に記載されているように、newおよびold "tables"を使用して、元の更新または挿入がテーブルに書き込む内容を変更して、 2回目の更新、つまり無限ループ。

3
RDFozz