假设我有一个带有表A,B和C的PostgreSQL数据库,其中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)。是否可以使用数据库约束检查此属性?
答案 0 :(得分:1)
您需求的更好方法是约束触发器。
它应该对表C执行exists()检查,并在所需的键不存在时引发异常。 (从技术上讲,这是强制执行外键约束的内置触发器。)
它会像:
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的奇怪边缘情况总是出现在我自己的经验中。