web-dev-qa-db-ja.com

PostgreSQL更新トリガー

私はテーブルを持っています:

CREATE TABLE annotations
(
  gid serial NOT NULL,
  annotation character varying(250),
  the_geom geometry,
  "rotationAngle" character varying(3) DEFAULT 0,
  CONSTRAINT annotations_pkey PRIMARY KEY (gid),
  CONSTRAINT enforce_dims_the_geom CHECK (st_ndims(the_geom) = 2),
  CONSTRAINT enforce_srid_the_geom CHECK (st_srid(the_geom) = 4326)
)

そしてトリガー:

CREATE TRIGGER set_angle
AFTER INSERT OR UPDATE
ON annotations
FOR EACH ROW
EXECUTE PROCEDURE setangle();

そして機能:

CREATE OR REPLACE FUNCTION setAngle() RETURNS TRIGGER AS $$
BEGIN
IF    TG_OP = 'INSERT' THEN
    UPDATE annotations SET "rotationAngle" = degrees( ST_Azimuth( ST_StartPoint(NEW.the_geom), ST_EndPoint(NEW.the_geom) ) )-90 WHERE gid = NEW.gid;
    RETURN NEW;
ELSIF TG_OP = 'UPDATE' THEN
    UPDATE annotations SET "rotationAngle" = degrees( ST_Azimuth( ST_StartPoint(NEW.the_geom), ST_EndPoint(NEW.the_geom) ) )-90 WHERE gid = NEW.gid;
    RETURN NEW;
END IF;
END;
$$ LANGUAGE plpgsql;

そして、新しい行がテーブルに挿入されたり、行が編集されたりしたときに、関数の結果をフィールドrotationAngleに設定したいと思います。しかし、テーブル関数に新しい行を挿入すると機能しません。つまり、rotationAngleの値は変更されていません。

何が間違っている可能性がありますか?

8
Kliver Max

@ SpartanEliteが指摘 のように、無限ループをトリガーしています。

トリガー機能を簡素化します。

CREATE OR REPLACE FUNCTION set_angle()
  RETURNS TRIGGER AS
$func$
BEGIN
   NEW."rotationAngle" := degrees(
                             ST_Azimuth(
                                ST_StartPoint(NEW.the_geom)
                              , ST_EndPoint(NEW.the_geom)
                             )
                          ) - 90;
   RETURN NEW;
END
$func$ LANGUAGE plpgsql;
  • NEWに直接割り当てます。この場合、WHEREはありません。
  • あなた必須不正な列名を二重引用符で囲みます。そもそもそのような名前を使わないほうがいいです。
    最近の関連回答。
  • 挿入とアップグレードのコードは同じです。私は1つのコードパスに折りたたまれました。

BEFOREトリガーを使用します。このようにして、トリガー行の列を直接編集できますbefore保存されます。

CREATE TRIGGER set_angle
BEFORE INSERT OR UPDATE ON annotations
FOR EACH ROW EXECUTE PROCEDURE set_angle();

しかしながら

If機能に依存する値をテーブルに保持しようとしているだけです(他の考慮事項はありません):しないでください。代わりに、ビューまたは生成された列を使用してください。

その後、これは必要ありません。

20

ここには複数の問題があります。 1)行 'A'を挿入すると、関数setAngle()が呼び出されます。しかし、関数では、関数内で別のupdateを呼び出して、関数を何度もトリガーします。これを修正するには、更新を発行しないでください。 NEWレコードの値を個別に更新して返すだけです。

3
SpartanElite