sql—使用触发器使用相关表中的最小值和最大值更新摘要表中的行

fzsnzjdm  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(373)

我有两张table, Order 以及 Slot . 每个插槽都有时间,但为了简单起见,我们假设它们是整数。像这样:

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

我在努力保持 earliest 以及 latest 更新如下: earliest = MIN(slot.time_from) 以及 latest = MAX(time_to) . 总是这样 time_from < time_to ,但这不重要。
为此,我在更新时创建了触发器,并在插槽中插入触发器。触发器:

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

类似地,如果我将时间从设置为小于10的值,它会更新。
我想我明白为什么会这样。每个槽更新块位于相关行上,允许同时运行更新。触发器只看到其事务更新的数据,而不看到其他事务更新的数据。结果,它计算tx1的min(10,15)和tx2的min(10,19),并按相关顺序将earliest设置为10。
我的理解正确吗?如何使这样的配置正常工作?

u3r8eeie

u3r8eeie1#

与其存储这些派生信息,为什么不创建一个视图呢?

create view v_orders as
select order_id, min(time_from) earlierst, max(time_to) latest
from slots
group by order_id

使用这种技术,您不必担心实际维护数据。该视图为您的数据提供始终最新的透视图。

相关问题