使用触发器使用相关表中的最小值和最大值更新汇总表中的行

问题描述 投票:0回答:1

我有两个表,OrderSlot。每个插槽都有时间,但为简单起见,我们将其表示为整数。像这样的东西:

Order              Slot
-----              ----
order_id           slot_id
earliest           order_id
latest             time_from
                   time_to

我正在尝试更新earliestlatest,以使earliest = MIN(slot.time_from)latest = MAX(time_to)time_from < time_to一直都是这种情况,但这在这里并不重要。

为此,我在UPDATE上创建了一个触发器,在Slot上创建了一个INSERT。触发器:

CREATE OR REPLACE FUNCTION keep_orders_updated() RETURNS trigger AS $trigger$
BEGIN

  UPDATE "order"
  SET earliest=d.earliest_min, latest=d.latest_max
  FROM (SELECT MIN(time_from) as earliest_min, MAX(time_to) AS latest_max FROM "slot" WHERE order_id = NEW.order_id) AS d
  WHERE order_id=NEW.order_id;

  RETURN NULL;
END;
$trigger$ LANGUAGE plpgsql;

CREATE TRIGGER keep_orders_updated_trigger AFTER INSERT OR UPDATE ON "slot" FOR EACH ROW EXECUTE PROCEDURE keep_orders_updated();

[在大多数情况下,它会产生正确的结果,除了以下情况,我正在尝试解决。我们从以下数据开始:

Order:
  order_id |   earliest    | latest     
 ----------+------------------------
     1     | 10            | 20


Slots:

  slot_id  | order_id | time_from   | latest         
 ----------+------------------------+------------------------
     1     | 1        | 10          | 12
     1     | 1        | 18          | 20

并且在两个并发事务中(在我的情况下,它们是使用来自Web服务器中连接池的不同连接运行的,基本上服务于大约同时到达的两个请求:]]

tx1: UPDATE "slot" SET time_from=15 AND time_to=17;
tx2: UPDATE "slot" SET time_from=19 AND time_to=25;

我获得了正确更新(预期)的广告位,并且订单更新错误。仅最新更新:

Order:
  order_id |   earliest    | latest     
 ----------+------------------------
     1     | 10            | 25

类似地,如果我将time_from设置为小于10的值,它将更新。

我想我理解为什么会这样。相关行上的每个插槽更新块均会阻止更新同时运行。触发器仅看到其事务更新的数据,而不看到其他事务更新的数据。结果,它为tx1计算MIN(10,15),为tx2计算MIN(10,19),并按照相关顺序将其最早设置为10。

我的理解正确吗?如何使这样的配置正常工作?

我有两个表,即Order和Slot。每个插槽都有时间,但为简单起见,我们将其表示为整数。像这样的东西:订单位----- ---- order_id slot_id ...

sql postgresql date concurrency database-trigger
1个回答
1
投票

代替存储此派生信息,为什么不创建视图?

© www.soinside.com 2019 - 2024. All rights reserved.