基于其他行中的值对行值的约束

Bra*_*ham 5 postgresql exclusion-constraint check-constraints

是否可以有一个包含四列的表:

CREATE TABLE accrual (
    add_date date NOT NULL,
    user_id integer NOT NULL,
    rate integer NOT NULL,
    amount numeric(7,3)
); 
Run Code Online (Sandbox Code Playgroud)

然后对其进行限制,以便如果我已经有一个条目,例如

('2016-04-01', 3, 120, 25.6)
Run Code Online (Sandbox Code Playgroud)

尝试插入具有相同日期和 user_id 但不同速率的另一个条目会失败吗?IE

('2016-04-01', 3, 140, 15)
Run Code Online (Sandbox Code Playgroud)

会失败,但是

('2016-04-02', 3, 140, 15)
Run Code Online (Sandbox Code Playgroud)

或者

('2016-04-01', 4, 140, 15)
Run Code Online (Sandbox Code Playgroud)

或者

('2016-04-01', 3, 120, 15)
Run Code Online (Sandbox Code Playgroud)

会好吗?

需要明确的是,日期和 user_id 基本上就像一个索引,除了重复索引完全没问题,只要费率相同。金额不受限制。

我正在使用 postrgesql 9.5 数据库,并且使用 PHP。我的猜测是,最简单的方法是编写一些 PHP 代码来执行检查。我能找到的最接近的问题是这个:

触发或检查约束根据其他值的存在插入值

但它是关于 Oracle 数据库的,并且略有不同。

感谢您的任何建议!

Bra*_*ham 4

正如@NeilMcGuigan 所建议的,排除约束是这里的关键。我不熟悉的部分是使用 <> 运算符的能力。Postgres 9.0 后可用:

CREATE TABLE accrual (
    add_date date NOT NULL,
    user_id integer NOT NULL,
    rate integer NOT NULL,
    amount numeric(7,3),
    EXCLUDE USING gist
        (date WITH =,
        user_id WITH =,
        rate WITH <>)
);
Run Code Online (Sandbox Code Playgroud)

两个有用的链接是:

  1. http://www.tutorialspoint.com/postgresql/postgresql_constraints.htm -- 关于 Postgres 中约束的简短教程,其中包含使用 <> 运算符的排除约束的示例

  1. http://www.slideshare.net/pgconf/not-just-unique-exclusion-constraints(特别是幻灯片 23)——关于排除约束的必要性和使用的演示。幻灯片 23 介绍了 <> 运算符及其用途。