我试图在PostgreSQL中创建一个触发器函数,在插入或更新记录之前,它应该检查具有相同id
的记录(即通过id
与现有记录进行比较)。如果该函数找到具有相同id
的记录,则该条目被设置为time_dead
。让我用这个例子来解释:
INSERT INTO persons (id, time_create, time_dead, name)
VALUES (1, 'now();', ' ', 'james');
我想要一张这样的table:
id time_create time-dead name
1 06:12 henry
2 07:12 muka
id 1
有一个time_create 06.12
,但time_dead
是NULL
。这与id 2
相同,但下次我尝试使用相同的id但不同的名称运行insert
查询时,我应该得到这样的表:
id time_create time-dead name
1 06:12 14:35 henry
2 07:12 muka
1 14:35 waks
亨利和waks共享相同的id
1
。在运行insert
查询后,henry的time_dead
等于waks的time_create
。如果另一个条目的id为1,比如james,james的时间条目将等于waks的time_dead
。依此类推。
到目前为止,我的函数看起来像这样。但它不起作用:
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
查询时,会给予我上面的结果?
我做错了什么?
两张table:
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);
1条答案
按热度按时间z2acfund1#
触发函数
你在触发器函数(
IF tg_op = ''UPDATE''
)中遗漏了INSERT
的情况。但是没有必要在开始时检查TG_OP
,因为触发器只在INSERT OR UPDATE
上触发-假设你在其他触发器中没有使用相同的函数。所以我删除了这个cruft。你不需要在一个用美元引号括起来的字符串中转义单引号。
还增加了:
...以防止
INSERT
立即终止自己(并导致 * 无限递归 *)。这假设一行永远不会继承具有相同name
的另一行。旁白:设置仍然不是防弹的。
UPDATE
s可能会扰乱你的系统。我可以继续更新id
或一行,从而终止其他行,但不留下后继行。考虑禁止在id
上更新。当然,这将使触发器ON UPDATE
毫无意义。我怀疑你一开始就需要它。DEFAULT now()
如果你想使用
now()
作为time_create
的默认值,只需这样做。Read the manual about setting a columnDEFAULT
。然后跳过INSERT
s中的time_create
,它会自动填充。如果你想强制它(防止每个人输入不同的值),创建一个触发器
ON INSERT
或在触发器的顶部添加以下内容:这将无条件地强制新行使用当前时间戳。
(假设列“time_create”实际上是
timestamp
类型。