检查最后一个最大值的约束

Check constraint on last max

如何对字段中的最后一个最大值进行检查约束?例如,在下面:

CREATE TABLE prisoner (
    prisoner_id    SERIAL4 PRIMARY KEY,
    name           TEXT NOT NULL CHECK(length(name) <= 256)
);

CREATE TABLE meals (
    prisoner_id       INT4 REFERENCES prisoner,
    last_meal_time    TIMESTAMP(6) WITH TIME ZONE NOT NULL DEFAULT now()        
);

如何确保 last_meal_time 始终比给定 prisoner_id 的最后一个最大值 last_meal_time >=?换句话说,我将无法追溯地给任何给定的囚犯喂另一顿饭。

设置主键:

create table meals (
    prisoner_id int4 references prisoner,
    last_meal_time timestamp with time zone not null default clock_timestamp(),
    primary key (prisoner_id, last_meal_time)
);

注意是clock_timestamp.

并始终插入默认值:

insert into meals (prisoner_id) values (1);

您可以在检查约束中使用函数,例如:

create table t(id serial, p int, ts timestamp);

create function t_max_time(p_id int) returns timestamp as $$ select max(ts) from t where p = p_id $$ language sql;

alter table t add constraint t_ts_check check (ts >= t_max_time(p));

-- Thanks to Clodoaldo Neto attention,
-- To prevent changes in other concurrent transactions while our transaction is active we can lock table for exclusive editing like:
lock table t in exclusive mode nowait;
-- It locks table or raises exception if table already locked by another transaction

insert into t(p, ts) values (1, '2016-02-02 10:10:10'), (1, '2016-02-02 11:11:11'); -- It works

insert into t(p, ts) values (1, '2016-02-02 09:09:09'); -- Constraint violation