Sql 是否对相关表中的值(而不是外键)进行部分索引?

Sql 是否对相关表中的值(而不是外键)进行部分索引?,sql,postgresql,database-design,constraints,postgresql-9.4,Sql,Postgresql,Database Design,Constraints,Postgresql 9.4,我正在一个学习平台上工作,在这个平台上,学生属于团队,每个团队都属于课程: CREATE TABLE teams ( id SERIAL, name string NOT NULL, curriculum_id integer NOT NULL ); CREATE TABLE curricula ( id SERIAL, name string NOT NULL ); CREATE UNIQUE INDEX index_curricula_on_nam

我正在一个学习平台上工作,在这个平台上,学生属于
团队
,每个团队都属于
课程

CREATE TABLE teams (
    id SERIAL,
    name string NOT NULL,
    curriculum_id integer NOT NULL
);

CREATE TABLE curricula (
    id SERIAL,
    name string NOT NULL
);

CREATE UNIQUE INDEX index_curricula_on_name ON curricula USING btree (name);
课程名称必须是唯一的,虽然大多数课程允许有多个团队与其关联,但一个团队不能。我试图在teams表上添加一个部分(唯一)索引,以便对课程设置进行限制

我知道我可以用…部分地约束课程id本身

CREATE UNIQUE INDEX index_teams_on_curriculum_id ON teams USING btree (curriculum_id)
WHERE curriculum_id = 1;
。。。但这是不可行的,因为课程的ID在不同的环境(开发、登台等)中会有所不同


有没有办法通过
课程名称来约束
团队.课程id
列?

您可以通过触发器或
检查约束中的假不可变函数来实现类似的功能。两者都有弱点

但这也可以通过纯SQL实现-仅使用
非空
检查
唯一
FK
约束。没有弱点

CREATE TABLE curriculum (
   curriculum_id serial PRIMARY KEY
 , curriculum    text UNIQUE NOT NULL
 , team_unique   boolean UNIQUE NOT NULL
 , CONSTRAINT curriculum_team_uni UNIQUE (curriculum_id, team_unique)  -- for multicolumn FK
);

CREATE TABLE team (
   team_id       serial PRIMARY KEY
 , team          text NOT NULL
 , curriculum_id integer NOT NULL
 , team_unique   boolean NOT NULL
 -- , CONSTRAINT fk1 FOREIGN KEY (curriculum_id) REFERENCES curriculum
 , CONSTRAINT fk2 FOREIGN KEY (curriculum_id, team_unique)
              REFERENCES curriculum (curriculum_id, team_unique)
);

CREATE UNIQUE INDEX team_curriculum_uni_idx ON team (team_unique)
WHERE team_unique;
  • 在父表和子表中添加一个
    boolean NOT NULL
    列,并在父表中使其
    唯一。因此,
    课程
    中只有一行可以标记为唯一-以实现您的限制性要求:

    不能

    部分唯一索引
    team\u currency\u uni\u idx
    仅强制对其进行一次引用

    如果有多个唯一的课程(仅参考一次),我们将删除
    课程.team\u unique
    上的
    unique
    约束,并将
    team
    上的部分唯一索引扩展到
    (课程id,team\u unique)

  • FK(
    fk2
    )强制继承列的组合

  • 这使得添加一个
    UNIQUE
    约束以强制一个团队执行唯一课程变得非常简单

  • Postgres FK约束的默认
    MATCH SIMPLE
    行为仅强制不带空值的组合。我们可以使用
    MATCH FULL
    或另一个普通FK(
    fk1
    )来强制执行现有的
    课程id
    。我对附加的FK进行了注释,因为在此配置中不需要它(定义的两个FK列均
    不为NULL

相关的:


@erwin感谢您的编辑和更好的标签!这真是不可思议的现象,谢谢你。我还没来得及通读所有这些内容并加以实施,但我想提前向你们表示感谢。@Kevlar:注意我添加的一个小简化。