1

レコードを挿入または更新する前に、PostgreSQL で同じレコードをチェックする (つまり、既存のレコードidと比較する)トリガー関数を作成しようとしています。id関数が同じ を持つレコードを見つけた場合、idそのエントリは に設定されますtime_dead。この例で説明しましょう:

INSERT INTO persons (id, time_create, time_dead, name)
VALUES (1, 'now();', ' ', 'james');

次のようなテーブルが欲しいです。

 id  time_create  time-dead  name
 1   06:12                   henry   
 2   07:12                   muka

id 1ありましたtime_create 06.12が、ありtime_deadましたNULL。これは と同じですが、次に同じ ID で異なる名前id 2のクエリを実行しようとすると、次のようなテーブルが得られるはずです。insert

 id  time_create  time-dead  name
 1   06:12        14:35      henry   
 2   07:12                   muka
 1   14:35                   waks

ヘンリーとワクスは同じものを共有していid 1ます。insertクエリを実行すると、henry'stime_deadは waks' と等しくなりtime_createます。別のエントリが id 1 で作成された場合、たとえば james の場合、james の時間エントリはtime_deadfor waks と同じになります。等々。

これまでのところ、私の機能は次のようになっています。しかし、それは機能していません:

CREATE FUNCTION tr_function() RETURNS trigger AS '
BEGIN
  IF tg_op = ''UPDATE'' THEN
     UPDATE persons
     SET time_dead = NEW.time_create
     Where
         id = NEW.id
         AND time_dead IS NULL
         ;

  END IF;
  RETURN new;
END
' LANGUAGE plpgsql;

CREATE TRIGGER sofgr BEFORE INSERT OR UPDATE
        ON persons FOR each ROW
        EXECUTE PROCEDURE tr_function();

私がこれを実行すると、発言time_deadは想定されていませんnulltrigger function自動的に時刻を入力するが、クエリinserting or updatingを実行すると上記の表のような結果が得られる を作成する方法はありますか?select

私は何を間違っていますか?

私の2つのテーブル:

CREATE TABLE temporary_object
(
  id integer NOT NULL,
  time_create timestamp without time zone NOT NULL,
  time_dead timestamp without time zone,
  PRIMARY KEY (id, time_create)
);

CREATE TABLE persons
(
  name text
)
INHERITS (temporary_object);
4

1 に答える 1

2

トリガー機能

CREATE FUNCTION tr_function()
  RETURNS trigger AS
$func$
BEGIN

   UPDATE persons p
   SET    time_dead = NEW.time_create
   WHERE  p.id = NEW.id
   AND    p.time_dead IS NULL
   AND    p.name <> NEW.name;

   RETURN NEW;

END
$func$ LANGUAGE plpgsql;
  • INSERTトリガー関数 ( ) でケースが欠落していましたIF tg_op = ''UPDATE''。ただし、他のトリガーで同じ関数を使用しないと仮定するTG_OPと、トリガーは起動するだけなので、最初からチェックする必要はありません。INSERT OR UPDATEだから私はクラフトを取り除きました。

  • ドル引用符で囲まれた文字列内の単一引用符をエスケープする必要はないことに注意してください。

  • また追加:

      AND    p.name <> NEW.name
    

... が即座に終了するのを防ぎます(そして無限再帰INSERTを引き起こします)。これは、行が同じ.name

余談: セットアップはまだ防弾ではありません。UPDATEs はシステムを台無しにする可能性があります。または行を更新し続けることで、id他の行を終了させて​​も、後続の行を残すことはできませんでした。での更新を禁止することを検討してくださいid。もちろん、それではトリガーがON UPDATE無意味になります。そもそもそれが必要だとは思えません。


now() をデフォルトとして

now()デフォルトとして使用したい場合はtime_create、そうしてください。列の設定に関するマニュアルを読んでくださいDEFAULT。次に s をスキップtime_createするINSERTと、自動的に入力されます。

強制的に実行したい(全員が異なる値を入力できないようにする) 場合は、トリガーを作成するON INSERTか、トリガーの先頭に次のコードを追加します。

IF TG_OP = 'INSERT' THEN
    NEW.time_create := now();   -- type timestamp or timestamptz!
    RETURN NEW;
END IF;

誤解を招く名前の列「time_create」が実際にはtimestampタイプであると仮定します。
これにより、新しい行の現在のタイムスタンプが強制されます。

于 2012-12-07T20:06:25.753 に答える