我有一张类似的表:
CREATE TABLE orders(
order_id UUID PRIMARY KEY,
owner_id TEXT,
other_data TEXT
)
我正在尝试对数据库执行insert-or-update类型的操作。我试图实现的逻辑是:
理想情况下,我希望使用postgresql文档中的custom UPSERT example将其实现为存储过程。
我遇到的问题是区分案例1和案例2.上面的案例,而不必进行两次单独的查询。如果我这样做:
UPDATE orders(other_data) WHERE order_id=order_id_param AND owner_id=owner_id_param;
然后如果没有匹配的订单我不知道是不是因为记录不存在,或者确实存在但owner_id不匹配。
当然,我可以在更新之前进行这样的初始查询:
SELECT count(1) FROM orders WHERE order_id=order_id_param AND owner_id!=owner_id_param;
如果返回的计数> 0,则抛出错误;但是如果可能的话,我想避免额外的查询。
我正在使用PostgreSQL 9.2。
我发现this similar SO question但它适用于SQL Server 2008,并且似乎没有以我可以简单地应用于PostgreSQL的方式解决它。
答案 0 :(得分:0)
最后,我通过定义一个触发器来解决这个问题,如果owner_id不匹配,该触发器会阻止表上的UPDATE查询成功。
这很简单,看起来像这样:
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();
在定义了这个之后,我定义了一个与PG docs中描述的相同的upsert过程。
感谢@Noran给我的想法。