理解 Postgres 中的继承;为什么插入/更新命令中的键“失败”

问题描述

(一张图,千言万语) 我制作了几个在它们之间继承的表。 (人) 然后分配子表(地址),并将其仅与“基”表(人)相关联。 当尝试在子表中插入,并且记录与继承表相关时,插入语句失败,因为主表中没有键。 当我在后代表中插入记录时,记录在基表中可用(因此,恕我直言,应该在继承表中可见/可访问)。 请查看附件图片。显然做错了什么或没有得到一些点...... 提前谢谢你!

enter image description here

解决方法

抱歉,这就是 Postgres 表继承的工作方式。 5.10.1 Caveats 解释。

继承特性的一个严重限制是索引(包括唯一约束)和外键约束仅适用于单个表,而不适用于它们的继承子表。在外键约束的引用侧和被引用侧都是如此。因此,在上面的例子中:

指定另一个表的列 REFERENCES city(name) 将允许另一个表包含城市名称,但不能包含大写名称。对于这种情况,没有好的解决方法。

在他们的示例中,capitals 从城市继承,而 organization_employees 从个人继承。如果 person_address REFERENCES person(idt_person) 它不会看到组织_employees 中的条目。


继承并不像看起来那么有用,也不是避免连接的方法。使用带有一些额外列的连接表可以更好地完成此操作。不清楚为什么一个组织会继承一个人。

person
  id bigserial primary key
  name text not null
  verified boolean not null default false
  vat_nr text
  foto bytea

# An organization is not a person
organization
  id bigserial not null
  name text not null

# Joins a person with an organization
# Stores information about that relationship
organization_employee
  person_id bigint not null references person(id)
  organization_id bigint not null references organization(id)
  usr text
  pwd text

# Get each employee,their name,and their org's name.
select
  person.name
  organization.name
from
  organization_employee
join person on person_id = person.id
join organization on organization_id = organization.id
  • 使用 bigserial (bigint) 作为主键,20 亿比你想象的要快
  • 不要在架构中包含任意的业务规则,例如名称可以有多长。您不会通过限制空间来节省任何空间,每次业务规则更改时,您都必须更改架构。使用文本类型。在应用程序中强制执行任意限制或作为约束。
  • idt_table_name 主键使得长的、不一致的列名难以猜测。为什么person_address的主键不是idt_person_address?为什么organization_employee的主键是idt_person?一眼就看不出哪个是主键,哪个是外键。您仍然需要在列名前加上以消除歧义;例如,如果您使用 person_address 加入 person,则需要 person.idt_personperson_address.idt_person。混乱和多余。 id(或 idt,如果您愿意)使主键很明显,并清楚地将其与 table_id(或 idt_table)外键区分开来。 SQL 已经有了解决歧义的方法:person.id