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

发布于 2024-11-29 10:36:44 字数 2493 浏览 1 评论 0 原文

我有一个问题,假设我有一个由学生表和教师表继承的人员表。如果我执行 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 是人员表上的主键)子表正在向 people 表进行插入,而不考虑该表的约束。 people 表上的主键约束不应该阻止创建重复记录吗?

我考虑过使用一个触发器来解决这个问题,该触发器将在人员表上进行插入之前触发,女巫会检查是否存在已存在的 P_Id。但我希望它要么阻止我做这样的事情,要么我希望它仅在子表中智能地创建一条记录

这样做之后,例如在学生表中更改姓氏并具有这些变化会反映到教师表上吗?

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

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)

I have a problem where lets say I have a people table that is inherited by a student table and a teacher table. if I do an INSERT INTO student and an INSERT INTO teacher and specify the primary key of the people table (P_Id) for example

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');

I wind up with two duplicate records in my people table (P_Id is my primary key on the people table) it appears that the sub-tables are doing the inserts into the people table without considering the constraints on that table. shouldn't the primary key constraint on the people table prevent duplicate records from being created?

I've thought about resolving this issue using a trigger that will fire before an insert is made on the people table witch would check for a P_Id that already exists. but I would like for it to either prevent me from doing such things or I would like it to intelligently create a record in the sub-table only

After doing this would there be an issue with changing the LastName for example in the student table and having the changes reflect onto the teacher table?

Here are the create statements the above Insert statements were only to give an example I understand they will not work with these tables that are created:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

初相遇 2024-12-06 10:36:44

我认为这种行为是设计使然的。来自 PostgreSQL 文档 。 。 。

INSERT 始终准确插入到指定的表中。

并且,在页面下方一点。 。 。

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

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

来自“注意事项”部分。 。 。

继承功能的一个严重限制是索引
(包括唯一约束)和外键约束仅适用
到单个表,而不是它们的继承子项。这是正确的
外键约束的引用端和被引用端。

同一段。

这些缺陷可能会在未来的版本中得到修复,但是
与此同时,在决定是否
继承对您的应用程序很有用。

I think this behavior is by design. From the PostgreSQL docs . . .

INSERT always inserts into exactly the table specified.

And, a little farther down the page . . .

All check constraints and not-null constraints on a parent table are
automatically inherited by its children. Other types of constraints
(unique, primary key, and foreign key constraints) are not inherited.

If you select only from people, you'll see no rows. If you select only from student, you'll see multiple rows with the same people_id. That is, you can insert into students multiple rows with the same value for people_id. This is counter-intuitive at best; the documentation says it's broken, but will probably be fixed someday.

From the "Caveats" section . . .

A serious limitation of the inheritance feature is that indexes
(including unique constraints) and foreign key constraints only apply
to single tables, not to their inheritance children. This is true on
both the referencing and referenced sides of a foreign key constraint.

Same section.

These deficiencies will probably be fixed in some future release, but
in the meantime considerable care is needed in deciding whether
inheritance is useful for your application.

明月夜 2024-12-06 10:36:44

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

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);

再见。

The constraint rules isn't inheritable, so you need to define the constraint in each table. For example:

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);

See you.

复古式 2024-12-06 10:36:44

你的主键字段设置是Identity吗?限制唯一性?

Is your primary key field set is Identity? to constrain the uniqueness?

梦忆晨望 2024-12-06 10:36:44

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

You never insert into the child tables first! The person table is the first table you should be inserting into.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文