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_deadNULL。这是相同的,id 2但下次我尝试insert使用相同的 id 但不同的名称运行查询时,我应该得到一个像这样的表:

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

henry 和 waks 共享 相同 的id 1. 运行insert查询后 henry's time_deadis equal to 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不应该是null. 有没有一种方法可以编写一个trigger function自动输入时间inserting or updating但在我运行查询时给我上表的结果select

我究竟做错了什么?

我的两张桌子:

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's 立即终止自身(并导致无限递归)。这假定一行永远不会在具有相同name.

另外:设置仍然不是防弹的。UPDATEs 可能会弄乱您的系统。我可以继续更新idor 一行,从而终止其他行但不留下后续行。考虑禁止更新id. 当然,这会使触发器ON UPDATE毫无意义。我怀疑你需要从这个开始。


现在()作为默认值

如果您想将其now()用作默认值,time_create只需这样做。阅读有关设置列的手册DEFAULT。然后跳过s time_createINSERT它会自动填充。

如果你想强制它(防止每个人输入不同的值)创建一个触发器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 回答