假设我有一个PostgreSQL数据库,其中有表A、B和C,其中A和B通过连接表C具有多对多关系。这些表有以下SQL定义:

CREATE TABLE A
(
  id serial NOT NULL,
  CONSTRAINT A_pkey PRIMARY KEY (id)
)

CREATE TABLE B
(
  id serial NOT NULL,
  CONSTRAINT B_pkey PRIMARY KEY (id)
)

CREATE TABLE C
(
  A_id integer NOT NULL,
  B_id integer NOT NULL,
  CONSTRAINT C_pk PRIMARY KEY (A_id, B_id),
  CONSTRAINT A_fk FOREIGN KEY (A_id)
      REFERENCES A(id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT B_fk FOREIGN KEY (B_id)
      REFERENCES B(id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

现在我要确保a的每个实例至少有一个b实例(换句话说:a中的每个id在c中至少作为a id出现一次)。是否可以使用数据库约束检查此属性?

最佳答案

满足您的需求的更好方法是约束触发器。
它应该做一个生存项()检查表C,并在不存在所需的密钥时引发异常。(从技术上讲,强制外键约束的内置触发器基本上就是这样做的。)
会变成这样:

create function A_C_fkey_check() returns trigger as $$
begin
  if not exists (select 1 from C where A_id = new.id) then
    raise exception 'invalid key';
  end if;
  return null;
end;
$$ language plpgsql;

create constraint trigger A_C_fkey_check after insert on A
for each row execute procedure A_C_fkey_check();

也就是说,我建议在数据库级别强制执行这种类型的约束并不是一个好主意:在我自己的经验中,总是会出现需要a而不是b的奇异边缘情况。

10-05 22:50
查看更多