0

現在の modified_at 列が更新で指定されたものよりも新しい場合、テーブルへの更新を拒否したい状況があります。CHECK 制約を使用してこれを実行しようとしましたが、効果がありません。

次に例を示します。

CREATE TABLE test (
    id SERIAL PRIMARY KEY,
    value INTEGER NOT NULL DEFAULT 0,
    modified_at timestamptz DEFAULT NOW()
);                  

ALTER TABLE test ADD CHECK (modified_at >= modified_at);

INSERT INTO test (id, value) VALUES (1, 1);
INSERT 0 1
SELECT * FROM test;
 id | value |          modified_at          
----+-------+-------------------------------
  1 |     1 | 2013-05-30 14:34:37.234456-07

UPDATE test
    SET value = 2, modified_at = NOW() - INTERVAL '1 day'                                                                              
WHERE id = 1;
UPDATE 1
SELECT * FROM test;
 id | value |          modified_at          
----+-------+-------------------------------
  1 |     2 | 2013-05-29 14:35:41.337543-07

これは期待どおりに機能していないようです。直感的に、これが問題であることがわかりました。プランナーは、左側が新しい値で、右側が古い値であることをどのように認識しますか?

これが機能しないことを知っている場合、この制約をどのように強制する必要がありますか?

4

2 に答える 2

3

更新された行の新しい modified_date に対して古い modified_date をチェックする必要があります。これはトリガーを使用して行うことができます。更新前に各行で実行するトリガーを設定し、それを処理する関数を作成して、古い modified_date を保持するか、更新をまったく実行しないかを選択します。

トリガーは次のように実行できます。

CREATE TRIGGER trigger_test
  BEFORE INSERT OR UPDATE
  ON test
  FOR EACH ROW
  EXECUTE PROCEDURE fn_trigger_test();

そして、このような機能:

CREATE OR REPLACE FUNCTION fn_trigger_test()
  RETURNS trigger AS
$BODY$
  DECLARE
BEGIN
IF (TG_OP = 'UPDATE') THEN
    IF NEW.modified_at<OLD.modified_at THEN

        RAISE EXCEPTION 'Date_modified older than previous';
        /* or to keep the old modified date:
             NEW.modifed_at=OLD.modified_at;
         RETURN NEW; */
    ELSE
        RETURN NEW;
    END IF;
END IF; 

END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
于 2013-05-31T01:42:56.493 に答える
2

CHECK 制約に関する限り、新しい値と古い値のようなものはありません。

PostgreSQL トリガーは新しいデータにアクセスできます。もう 1 つのかなり一般的な方法は、テーブルに対するアクセス許可を取り消し、すべてのアクセスがストアド プロシージャを介して行われるようにすることです。ストアド プロシージャは新しいデータにアクセスし、パラメーターを介して渡すことができ、ストアド プロシージャはテーブル内の値をチェックしたり、監査のために追加のテーブルを更新したりできます。 CREATE FUNCTIONおよびplpgsqlを参照してください。

于 2013-05-30T22:08:41.750 に答える