【问题标题】:postgresql how stop trigger adding a row if nothing has changed如果没有任何变化,postgresql如何停止触发添加行
【发布时间】:2019-07-03 18:37:44
【问题描述】:

我想将我的 working 表的更改记录到我的 history 表中,但只有在 UPDATE 期间值已更改时,我尝试创建一个 update_history 触发器,但无论值是否已被更改,它都会添加一行改变与否,例如说我的工作表中有这个:

shift_id|site     |organisational_unit
--------|---------|-------------------
  123475|site01   |my org              

如果我执行更新查询

UPDATE working SET site = $1, organisational_unit = $2 WHERE shift_id=$3', ['site01', 'my new org', '123475']

这会在 site 的历史表中创建一行,即使它没有更改值我只想要一个新行来更改组织单位

historyid|shiftid|fieldname          |oldvalue |newvalue   |updatedat          |
---------|-------|-------------------|---------|-----------|-------------------|
        7| 123475|organisational_unit|my org   |my new org |2019-07-01 10:21:19|
        8| 123475|site               |site01   |site01     |2019-07-01 10:21:19|

我的触发器是这样的

-- create function for updates to track history
CREATE function update_history ()
RETURNS TRIGGER
as $$
BEGIN
    -- check if data in column has changed between the update
    IF NEW.client_id <> OLD.client_id THEN

        -- if it has insert a row to the history table detailing the changes
        INSERT INTO history (ShiftId, fieldName, OldValue, NewValue)
        VALUES(New.shift_id, 'client id ', OLD.client_id, NEW.client_id);

    -- if nothing has changed don't do anything
    END IF;

    IF NEW.organisational_unit <> OLD.organisational_unit THEN
        INSERT INTO history (ShiftId, fieldName, OldValue, NewValue)
        VALUES(New.shift_id, 'organisational_unit', OLD.organisational_unit, NEW.organisational_unit);
    END IF;

    IF NEW.site <> OLD.site THEN
    INSERT INTO history
        (ShiftId, fieldName, OldValue, NewValue)
    VALUES(New.shift_id, 'site', OLD.site, NEW.site);
    END IF;

return null;
END;
$$
language plpgsql;

【问题讨论】:

标签: postgresql


【解决方案1】:

最有效的方法是定义一个仅在某些列更改时触发的触发器:

CREATE TRIGGER ... BEFORE UPDATE ON ... FOR EACH ROW
   WHEN (NEW IS DISTINCT FROM OLD)
   EXECUTE FUNCTION update_history();

这样可以避免在不必要的情况下执行该功能。

【讨论】:

    【解决方案2】:

    要检查列是否已更改,请不要使用&lt;&gt;。它不考虑空值。使用IS DISTINCT FROM

    IF NEW.client_id IS DISTINCT FROM OLD.client_id
    ...
    

    或者使用IF NEW IS DISTINCT FROM OLD检查整行

    如果你想防止插入主表发生,它应该是一个BEFORE UPDATE触发器,你应该做一个

    return null;

    仅在您不想要INSERT 的地方

    【讨论】:

    • 或者检查整行:if new is distinct from old
    • 加:OP可以将条件移动到触发器(他没有显示)
    • 太棒了,这正是我想要的 :)
    猜你喜欢
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 2014-12-20
    • 2017-10-17
    • 1970-01-01
    • 2011-03-08
    相关资源
    最近更新 更多