Postgresql 如何使用附加标准实现upsert

Postgresql 如何使用附加标准实现upsert,postgresql,postgresql-9.2,Postgresql,Postgresql 9.2,我有一张类似的桌子: CREATE TABLE orders( order_id UUID PRIMARY KEY, owner_id TEXT, other_data TEXT ) 我正在尝试对数据库执行插入或更新类型的操作。我试图实现的逻辑如下: 如果已存在具有给定订单id的记录,且给定所有者id匹配,则更新该记录 否则,如果已存在具有给定订单id的记录,且给定所有者id不匹配,则抛出错误 否则,请插入新记录 理想情况下,我希望以postgresql文档中的为例,将

我有一张类似的桌子:

CREATE TABLE orders(
    order_id UUID PRIMARY KEY,
    owner_id TEXT,
    other_data TEXT
)
我正在尝试对数据库执行插入或更新类型的操作。我试图实现的逻辑如下:

  • 如果已存在具有给定订单id的记录,且给定所有者id匹配,则更新该记录
  • 否则,如果已存在具有给定订单id的记录,且给定所有者id不匹配,则抛出错误
  • 否则,请插入新记录
  • 理想情况下,我希望以postgresql文档中的为例,将其实现为一个存储过程

    我遇到的问题是区分案例1。案例2。在上面,无需执行两个单独的查询。如果我这样做:

    UPDATE orders(other_data) WHERE order_id=order_id_param AND owner_id=owner_id_param;
    
    然后,如果没有匹配的订单,我将不知道这是因为记录不存在,还是它确实存在但所有者id不匹配

    当然,我可以在更新之前进行如下初始查询:

    SELECT count(1) FROM orders WHERE order_id=order_id_param AND owner_id!=owner_id_param;
    
    如果返回的计数>0,则抛出一个错误;但如果可能的话,我想避免额外的查询

    我正在使用PostgreSQL 9.2


    我发现,但它是针对SQL Server 2008的,似乎无法以我可以简单应用于PostgreSQL的方式解决它。

    最后,我通过定义一个触发器来解决这个问题,该触发器可以防止在所有者id不匹配的情况下对表进行更新查询

    它非常简单,看起来像这样:

    CREATE OR REPLACE FUNCTION order_update_check() 
    RETURNS trigger
    AS $$
    BEGIN
        IF NEW.owner_id != OLD.owner_id THEN
            RAISE EXCEPTION 'User % cannot modify order %', NEW.owning_user, OLD.order_id;
        END IF;
        RETURN NEW;
    END;
    $$
    LANGUAGE plpgsql;
    
    CREATE TRIGGER order_update_trigger BEFORE UPDATE ON orders
        FOR EACH ROW EXECUTE PROCEDURE order_update_check();
    
    定义了这一点之后,我定义了一个upsert过程,与中所述的过程基本相同


    感谢@Noran给了我这个想法。

    使用触发器。。。这是他们的工作。你的意思是,定义一个触发器,如果更新试图更改所有者id的值,它会引发错误。。。事实上这不是个坏主意