【发布时间】:2012-01-27 11:26:25
【问题描述】:
我有一个这样的 pg 表:
CREATE TABLE order_status_history (
order_id integer NOT NULL,
status character varying NOT NULL,
sequence integer DEFAULT 1 NOT NULL,
date_status timestamp with time zone DEFAULT now() NOT NULL,
record_state character varying(12) DEFAULT 'ACTIVE'::character varying NOT NULL
);
在 order_id 和序列上使用复合 PK。 本质上,对于每个单独的 order_id,状态列是一个从 1 开始的自动递增值。因此,如果 order_id 2 已经有两行,则序列将为 1 和 2,对于新行,序列应为 3。 我试图在插入之前使用触发器来实现此行为,但是当我尝试为新的 order_id 插入第一行时(即触发器不必在插入之前更改行),我得到了一个错误为PG。说它不能将 NULL 插入序列中。我看不到我的触发函数将如何返回 NULL,但我的 pl/sql 不是很好,所以我确定这很简单...下面的触发函数,谢谢。
DECLARE
seq_no INTEGER;
BEGIN
SELECT INTO seq_no MAX(sequence) FROM rar.order_status_history WHERE order_id = NEW.order_id;
IF FOUND THEN
NEW.sequence := seq_no + 1;
END IF;
RETURN NEW;
END;
【问题讨论】:
-
使用
SELECT max()获取新ID 是一个非常非常糟糕的主意。它不是交易安全的,您的解决方案将在多用户环境中创建错误的序列号。 -
@a_horse_with_no_name,很好,谢谢,有没有更好的方法来实现这一点?
-
如果你想让那个事务安全,你必须独占锁定表。
标签: sql postgresql triggers insert plpgsql