【问题标题】:PSQL trigger and function pair bug on INSERTINSERT 上的 PSQL 触发器和函数对错误
【发布时间】:2020-09-11 19:33:05
【问题描述】:

我有一张桌子 (time TIMESTAMP PRIMARY KEY, pressure REAL NOT NULL)。我需要开发一个触发器/函数对来执行此操作:如果插入新条目,则根据时间戳更新现有条目或插入新条目。

触发代码:

CREATE TRIGGER trigger_insert
    BEFORE INSERT ON mytable
    FOR EACH ROW
    EXECUTE PROCEDURE func_insert();

函数方法:

create or replace function func_insert()
returns trigger
language plpgsql
as
$$
DECLARE
    time_exists TIMESTAMP;
    BEGIN
        IF pg_trigger_depth() <> 1 THEN
            RETURN NEW;
        END IF;
        SELECT time INTO time_exists FROM mytable WHERE time = NEW.time;
    IF NOT FOUND THEN
        INSERT INTO mytable VALUES(NEW.*);
    ELSE 
        UPDATE mytable SET pressure = NEW.pressure WHERE time = NEW.time;
    END IF;
    RETURN NEW;
END;
$$;

讨论:

  1. 没有IF pg_trigger_depth() &lt;&gt; 1 THEN条件,脚本会导致深度触发溢出异常。

  2. 问题是在将第一个(原文如此!)条目插入空(原文如此!)表时出现错误:

    psycopg2.errors.UniqueViolation:重复键值违反唯一约束“mytable_pkey” DETAIL:key ("time")=(2019-06-01 00:00:00) 已经存在。

谢谢。

【问题讨论】:

    标签: postgresql triggers sql-insert plpgsql


    【解决方案1】:

    如果要插入该行,只需返回new,而不是再次尝试重新插入。

    如果要更新行,不要返回new,否则会被插入...

    话虽如此,做一个 upsert 是最干净的解决方案

    INSERT INTO myTable (time, pressure) VALUES (..., ...)
      ON CONFLICT (time)
        DO UPDATE SET pressure = EXCLUDED.pressure;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-17
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多