即使设置了主键约束,SQL表继承也会在基表中导致重复记录

时间:2011-08-12 15:56:24

标签: sql postgresql inheritance constraints

我有一个问题,我可以说我有一个由学生表和教师表继承的人员表。如果我执行INSERT INTO学生和INSERT INTO老师并指定人员表的主键(P_Id),例如

INSERT INTO student(P_Id, LastName, FirstName, StudentNumber)
VALUES (1, 'Jones', 'Casey', 'SID0001');

INSERT INTO teacher(P_Id, LastName, FirstName, FacultyNumber)
VALUES (1, 'Jones', 'Casey', 'JONES0001');

我最终在我的人员表中有两个重复的记录(P_Id是我在人员表上的主键),似乎子表正在插入人员表而不考虑该表的约束。人员表上的主键约束不应该阻止创建重复记录吗?

我已经考虑过使用触发器解决此问题,该触发器将在人员表上进行插入之前触发,该表将检查已存在的P_Id。但我希望它能阻止我做这些事情,或者我希望它只在子表中智能地创建记录

执行此操作后,如果在学生表中更改LastName并将更改反映到教师表上会有问题吗?

以上是上述插入语句的创建语句只是为了给出一个例子,我知道它们不适用于这些创建的表:

CREATE TABLE people
(
people_id integer NOT NULL,
last_name character varying NOT NULL,
first_name character varying NOT NULL,
middle_name character varying,
gender character varying NOT NULL,
date_of_birth date,
ssn character varying,
pref_language character varying,
CONSTRAINT people_pkey PRIMARY KEY (people_id)
)

CREATE TABLE student
(
-- Inherited from table people:  people_id integer NOT NULL,
-- Inherited from table people:  last_name character varying NOT NULL,
-- Inherited from table people:  first_name character varying NOT NULL,
-- Inherited from table people:  middle_name character varying,
-- Inherited from table people:  gender character varying NOT NULL,
-- Inherited from table people:  date_of_birth date,
-- Inherited from table people:  ssn character varying,
-- Inherited from table people:  pref_language character varying,
student_id integer NOT NULL,
race character varying(80),
ethnicity character varying(80),
employer character varying(80),
school character varying(80),
pref_location character varying(80),
CONSTRAINT student_pkey PRIMARY KEY (student_id)
)
INHERITS (people)

CREATE TABLE teacher
(
-- Inherited from table people:  people_id integer NOT NULL,
-- Inherited from table people:  last_name character varying NOT NULL,
-- Inherited from table people:  first_name character varying NOT NULL,
-- Inherited from table people:  middle_name character varying,
-- Inherited from table people:  gender character varying NOT NULL,
-- Inherited from table people:  date_of_birth date,
-- Inherited from table people:  ssn character varying,
-- Inherited from table people:  pref_language character varying,
teacher_id integer NOT NULL,
user_name character varying NOT NULL,
"password" character varying NOT NULL,
title character varying,
CONSTRAINT teacher_pkey PRIMARY KEY (teacher_id)
)
INHERITS (people)

4 个答案:

答案 0 :(得分:5)

我认为这种行为是设计的。来自PostgreSQL docs。 。

  

INSERT总是插入到指定的表中。

而且,页面稍远一些。 。

  

父表上的所有检查约束和非空约束都是   由其子女自动继承。其他类型的约束   (唯一,主键和外键约束)不会被继承。

如果您只选择人,则不会看到任何行。如果您只选择学生,您会看到多行具有相同的people_id。也就是说,您可以向学生插入多个具有相同值的people_id。这充其量是违反直觉的;文档说它已经坏了,但有一天可能会被修复。

来自“警告”部分。 。

  

继承功能的一个严重限制是索引   (包括唯一约束)和外键约束仅适用   单个表,而不是他们的继承子。这是真的   外键约束的引用和引用方。

相同部分。

  

这些缺陷可能会在未来的某个版本中修复,但是   与此同时,在决定是否需要时要非常小心   继承对您的应用程序很有用。

答案 1 :(得分:5)

约束规则不可继承,因此您需要在每个表中定义约束。例如:

CREATE TABLE people (
    id int ,
    name varchar(20),
    CONSTRAINT people_pkey PRIMARY KEY (id)
);

CREATE TABLE individual (
    cpf varchar(11),
    CONSTRAINT individual_pkey PRIMARY KEY (id)
) INHERITS (people);


CREATE TABLE legal_entity (
    cnpj varchar(14),
    CONSTRAINT legal_entity_pkey PRIMARY KEY (id)
) INHERITS (people);

见。

答案 2 :(得分:1)

您的主键字段是否为Identity?约束唯一性?

答案 3 :(得分:0)

您永远不会先插入子表!人员表是您应该插入的第一个表。