PostgreSQL:约束,仅当值存在于另一个表中时才在列中插入值

PostgreSQL:约束,仅当值存在于另一个表中时才在列中插入值,postgresql,Postgresql,我想给我的student表添加一个约束,这样在其majors列中输入的任何值都必须存在于majors表中。我该怎么做?这是外键约束 ALTER TABLE student ADD CONSTRAINT somename FOREIGN KEY (major_id) REFERENCES major (id); 请注意,如果student.major_id可为null,则列的值仍可为null 请注意,您的表不包含双专业。要做到这一点,我们需要一个student_major表,它是stud

我想给我的student表添加一个约束,这样在其majors列中输入的任何值都必须存在于majors表中。我该怎么做?

这是外键约束

ALTER TABLE student 
 ADD CONSTRAINT somename 
 FOREIGN KEY (major_id) REFERENCES major (id);
请注意,如果student.major_id可为null,则列的值仍可为null

请注意,您的表不包含双专业。要做到这一点,我们需要一个student_major表,它是student和major之间的多对多关系。这还演示了在create表中而不是在alter表中创建外键

create table student_major (
 id serial not null unique primary key,           -- optional, but good idea
 student_id int not null references student(id),  -- fk 
 major_id int not null references major(id),      -- fk
 UNIQUE (student_id, major_id)                    -- no redundant relations
);
评论:

-1用于拒绝复合密钥比尔·卡温

让我明白这一点。比尔同意我正确地回答了OP关于约束的问题。他同意我正确地看到了OP没有问到的东西,可能是双专业。但比尔仍然认为这个答案是错误的,因为我和比尔对复合钥匙的看法不一致

我甚至没有说需要合成身份证;事实上,我明确表示这是可选的,但我认为这是一个好主意。(为什么?它对删除、可能引用学生大学专业的表以及通常使用的ORM和生成的代码“发挥得更好”)


比尔,坦率地说,这太小气了。你在精化(学生:专业是M:M而不是M:1)上的精化(复合/合成)和什么是“宗教”战争上记下了正确答案。你是否因为不同意回答者关于标签与空格或vi与emacs的立场而记下正确答案?也许你应该花点时间给出自己的答案,而不是记下正确的答案。

好建议,但不要再写无用的序列号“PK”列,只需将(学生号、专业号)作为PK即可。没有理由在这里引入一个毫无价值的代理键。复合键是个麻烦事。为了与kquinn的建议保持一致,你还需要删除majors.major_id和student.student_id字段,除非它们是事实而不是代理项,这取决于使student和majors独一无二的字段的类型和数量,代理键可能正是所需要的。我认为,仅仅为了避免复合键而使用多余的ID列比复合键本身更重要。您已经指定了唯一约束,使其成为主键,从而批准了设计。在这种情况下,ID列不会增加任何价值,也会影响设计。我认为不应该有ID列,但它不会改变tpdi回答hassan问题的部分是100%正确的这一事实。基于这样的标准(自然键与代理键)进行修改是疯狂的。