8

次のコードスニペットを持つテーブルテストのトリガー関数があります。

IF TG_OP='UPDATE' THEN
    IF OLD.locked > 0 AND
 (       OLD.org_id <> NEW.org_id OR
            OLD.document_code <> NEW.document_code OR
            -- other columns ...
 )
THEN
    RAISE EXCEPTION 'Message';
-- more code

そのため、整合性を確保するために、すべての列の新しい値を以前の値と静的にチェックしています。これで、ビジネスロジックが変更され、そのテーブルに新しい列を追加する必要があるたびに、このトリガーを毎回変更する必要があります。どういうわけか、名前を明示的に入力せずに、そのテーブルのすべての列を動的にチェックできるとよいと思いました。

どのようにそれを行うことができますか?

4

5 に答える 5

12

トリガーの句に関する9.0beta2ドキュメントからWHEN、トリガー本体内の以前のバージョンで使用できる可能性があります。

OLD.* IS DISTINCT FROM NEW.*

またはおそらく(8.2リリースノートから

IF row(new.*) IS DISTINCT FROM row(old.*)

于 2010-06-21T11:33:09.877 に答える
11

information_schemaを見てください。「列」というビューがあります。クエリを実行して、トリガーを起動したテーブルから現在のすべての列名を取得します。

SELECT 
    column_name 
FROM 
    information_schema.columns 
WHERE 
    table_schema = TG_TABLE_SCHEMA 
AND 
    table_name = TG_TABLE_NAME;

結果をループして、そこに行きます!

詳細については、細かいマニュアルを参照してください。

于 2010-06-21T11:18:56.363 に答える
3

Postgres 9.0以降では、トリガー定義(ステートメント)にWHEN句を追加します。CREATE TRIGGER

CREATE TRIGGER foo
BEFORE UPDATE
FOR EACH ROW
WHEN (OLD IS DISTINCT FROM NEW)  -- parentheses required!
EXECUTE PROCEDURE ...;

とが両方とも定義されているトリガーBEFORE/でのみ可能です。またはトリガーでこの句を使用しようとすると、例外が発生します。AFTER UPDATEOLDNEWWHENINSERTDELETE

そしてそれに応じてトリガー関数を根本的に単純化します:

...
IF OLD.locked > 0 THEN
   RAISE EXCEPTION 'Message';
END IF;
...

IF TG_OP='UPDATE' ...このトリガーはとにかくのみ機能するため、テストする必要はありませんUPDATE

または、その条件をWHEN句でも移動します。

CREATE TRIGGER foo
BEFORE UPDATE
FOR EACH ROW
WHEN (OLD.locked > 0
  AND OLD IS DISTINCT FROM NEW)
EXECUTE PROCEDURE ...;

RAISE EXCEPTIONトリガー関数に無条件のみを残します。これは、最初に必要な場合にのみ呼び出されます。

詳細の閲覧:

BEFOREトリガーでは、WHEN関数が実行される直前または実行される直前に条件が評価されるため、を使用することWHENは、トリガー関数の開始時に同じ条件をテストすることと実質的に違いはありません。NEW特に、条件によって表示される行は現在の値であり、以前のトリガーによって変更された可能性があることに注意してください。また、BEFOREトリガーの条件では、行のシステム列(など)WHENを調べることはできません。これは、それらがまだ設定されていないためです。NEWoid

AFTERトリガーでは、WHEN行の更新が発生した直後に条件が評価され、ステートメントの最後にトリガーを起動するためにイベントがキューに入れられているかどうかが判別されます。したがって、AFTERトリガーの WHEN条件がtrueを返さない場合、イベントをキューに入れたり、ステートメントの最後で行を再フェッチしたりする必要はありません。これにより、トリガーをいくつかの行に対してのみ起動する必要がある場合、多くの行を変更するステートメントの速度が大幅に向上する可能性があります。

関連している:

質問のタイトルにも対処する

テーブルの列を動的にループすることは可能ですか?

はい。例:

于 2018-04-09T21:33:21.393 に答える
2

トリガー内のRECORD変数の反復

于 2012-03-02T08:24:57.480 に答える
1

pl/perlまたはpl/pythonを使用します。それらはそのようなタスクにはるかに適しています。はるかに良い。

hstore-newをインストールして、row-> hstoreセマンティクスを使用することもできますが、通常のデータ型を使用する場合は、これは絶対に良い考えではありません。

于 2010-06-21T21:55:10.100 に答える