【问题标题】:Postgres table inheritance: move from parent to child and vice versaPostgres 表继承:从父级移动到子级,反之亦然
【发布时间】:2015-04-08 08:06:28
【问题描述】:

我想知道如何在 PostgreSQL (9.4) 中轻松地在父表和子表之间移动数据,反之亦然。

假设我设置了以下数据库示例:

DROP TABLE IF EXISTS employee CASCADE;
DROP TABLE IF EXISTS director CASCADE;

CREATE TABLE employee(
id SERIAL PRIMARY KEY NOT NULL,
name VARCHAR(255) NOT NULL,
surname VARCHAR(255) NOT NULL,
employment_date DATE NOT NULL DEFAULT CURRENT_DATE
);

CREATE TABLE director(
director_id SERIAL PRIMARY KEY NOT NULL,
secretary_id INT4 REFERENCES employee(id),
extra_legal_benefits VARCHAR(255) ARRAY
) inherits (employee);

INSERT INTO employee(name, surname)
VALUES ('Alice', 'Alisson');

INSERT INTO employee(name, surname)
VALUES ('Bob', 'Bobson');

INSERT INTO employee(name, surname)
VALUES ('Carol', 'Clarckson');

INSERT INTO director(name, surname, secretary_id, extra_legal_benefits)
VALUES ('David', 'Davidson', 1, '{car, travel expenses}');

如何将其中一名员工提升(移动)到主管表(必须不再出现在父表中)?

我怎样才能将其中一位董事降级(移动)回员工表(必须不再出现在子表中)?

【问题讨论】:

  • VARCHAR(255)- 你知道 255 的限制没有特殊意义,隐藏优化或一些神奇的性能优势与例如值相比376 还是 52957?

标签: postgresql inheritance parent-child


【解决方案1】:

提拔员工:

with deleted as (
  delete from only employee 
  where name = 'Carol'
  returning *
)
insert into director (name, surname, secretary_id, extra_legal_benefits)
select name, surname, null, '{flight}'
from deleted;

但是:

不能再出现在父级中

根据定义,子表中的任何行都可以在父表中使用。如果在从员工表中选择时使用谓词 only,则只能“隐藏”这些行:

select *
from only employee;

以上内容不会显示同时担任董事的员工。一个普通的select * from employee 但是显示所有名称(但你无法区分它们 - 这是继承的本质)。


降级导演:

with deleted as (
  delete from only director 
  where name = 'David'
  returning *
)
insert into employee (name, surname)
select name, surname
from deleted;

但老实说,我可能会通过员工实体上的附加列(如positionrole)而不是使用继承来对此进行建模。甚至是与position(或role)实体的多对多关系,因为员工具有多个角色并不少见,例如在不同的部门、团队或其他环境中。

【讨论】:

  • 非常感谢您准确详细的回答。我完全同意您的评论,即这可以在真实的生产数据库中进行建模。但是作为一个示例,它非常适合理解和解释我遇到的继承问题。
  • postgresql 是否允许使用这个 delete-insert 构造保留一个 id 列,例如 id SERIAL PRIMARY KEY
  • @retorquere 默认情况下,子表不继承约束。但是,如果您专门将相同的 pk 序列和约束添加到子表中,您将得到唯一的约束违规。
  • @deinspanjer 所以如果我理解正确,我想对父表和子表都应用的任何约束都必须在两者中实现?
  • @retorquere 是的。阅读有关表继承的 pg 文档。约束不继承。这意味着如果父表具有id SERIAL PRIMARY KEY 的声明,您可以在父表中插入 id = 1,然后在子表中插入 id = 1,因为子表的 id 列将只是由没有约束的序列生成的普通 INT。要获得约束,在创建子表之后,CREATE UNIQUE INDEX child_uidx ON child(id);ALTER TABLE child ADD PRIMARY KEY USING INDEX child_uidx; 当然,如果你尝试上面答案中的代码,你会得到我提到的违规。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 2012-07-13
  • 1970-01-01
  • 2016-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多