3

私は2つのテーブルを持っています

 batch (batch_id,start_date,end_date,batch_strength,is_locked)
 sem (user_id,is_active,no_of_days)

以下に示すトリガー手順を実行してから、クエリを使用してテーブルを更新しました

CREATE OR REPLACE FUNCTION em_batch_update()
  RETURNS trigger AS $em_sem_batch$
BEGIN

UPDATE batch set is_locked='TRUE'
where (start_date
       + (select no_of_days from sem
          WHERE is_active='TRUE' and user_id='OSEM')
      ) <= current_date;

return NEW;

END;
$em_sem_batch$  LANGUAGE plpgsql;

CREATE TRIGGER em_sem_batch
BEFORE UPDATE ON batch FOR EACH ROW EXECUTE PROCEDURE em_batch_update();

update em_batch set batch_strength=20 where batch_id='OD001C001B3';

エラーがおきました:

エラー:スタックの深さの制限を超えまし
たヒント:プラットフォームのスタックの深さの制限が適切であることを確認した後、構成パラメーター "max_stack_depth"(現在は2048kB)を増やしてください。

4

3 に答える 3

7

トリガーに組み込んだ無限再帰を防ぐ方法はいくつかありますが、最もエレガントでパフォーマンスの高い方法は、おそらくトリガー関数WHEREのステートメントに句を追加することです。UPDATE

CREATE OR REPLACE FUNCTION em_batch_update()
  RETURNS trigger AS
$func$
BEGIN

UPDATE batch b
SET    is_locked = TRUE
FROM   sem s
WHERE  s.is_active
AND    s.user_id = 'OSEM'
AND    b.start_date <= (current_date - s.no_of_days)
AND    b.is_locked IS DISTINCT FROM TRUE; -- prevent infinite recursion!

RETURN NULL;

END
$func$  LANGUAGE plpgsql;

CREATE TRIGGER em_sem_batch
BEFORE UPDATE ON batch
FOR EACH STATEMENT
EXECUTE PROCEDURE em_batch_update();

私は正気に向かうために他のいくつかのことを変更しました:

ステートメントごとのトリガーによって呼び出されるトリガー関数は、常に NULL を返す必要があります。

  • batch.is_lockedsem.is_activeブール列のように見えます。適切なbooleanデータ型を使用してください。私のコードはそれに基づいています。

  • UPDATEまた、クエリを完全に書き直しました。特に、batch.start_date利用可能な場合にインデックスを使用できるようにするための条件。

  • batch.is_lockedが定義されている場合NOT NULLWHERE条件は次のように簡略化できます。

        AND    b.is_locked = FALSE;
    
于 2013-02-10T08:55:27.707 に答える
6

トリガーは同じテーブルでUPDATE別のトリガーを実行UPDATEします。これにより、トリガーが再度起動されるため、無限再帰が発生します。おそらくこれを少し再設計する必要がありますが、何をしようとしているのかを説明せずにその方法を言うのは難しいです。

于 2013-01-03T13:30:03.930 に答える