PostgreSQL触发器:仅在更新行上更新后触发。

4

我有一个新闻小表格。我想创建一个触发器来在行中设置更新日期和更新时间(只针对已更新的行)。

我尝试制作以下内容:

CREATE FUNCTION add_update_dates()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
  IF (OLD.news_name IS DISTINCT FROM NEW.news_name OR
  OLD.news_description IS DISTINCT FROM NEW.news_description OR
  OLD.news_text IS DISTINCT FROM NEW.news_text) THEN
  UPDATE news SET news_update_date = current_date, news_update_time = current_time;
END IF;
RETURN new;
END
$$;

CREATE TRIGGER update_news_dates
AFTER UPDATE ON news
FOR EACH ROW
EXECUTE PROCEDURE add_update_dates();

但是触发器会更新我的表中的每一行(即使是没有更新的行),而我只想更新那些被更新过的行。我哪里做错了吗?


在Postgresql中,触发器内的更新表语句是否允许在同一张表上进行?我的意思是,在Oracle中,我们会收到一个变异表错误。 - Kaushik Nayak
@KaushikNayak: 我认为在AFTER UPDATE触发器中允许,但不在BEFORE UPDATE触发器中允许。 - Nick Barnes
1个回答

9

你的update语句正在更新表中的所有行!它没有where子句。

只需使用赋值:

CREATE FUNCTION add_update_dates()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
  IF (OLD.news_name IS DISTINCT FROM NEW.news_name OR
      OLD.news_description IS DISTINCT FROM NEW.news_description OR
      OLD.news_text IS DISTINCT FROM NEW.news_text
     ) THEN
    NEW.news_update_date := current_date;
    NEW.news_update_time := current_time;
  END IF;
  RETURN new;
END;
$$;

顺便说一句,将日期/时间存储在单独的列中对我来说没有意义。


2
你还需要将触发器定义更改为 BEFORE UPDATE - Nick Barnes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接