table 模式 [PostgreSQL] 中的先有鸡还是先有蛋的问题
Chicken or Egg problem in table schema [PostgreSQL]
如何在 PostgreSQL 中创建行并将其插入到以下 table 模式:
Table: employee
emp_id, emp_name, emp_dept, emp_manager
Table: department
dept_id, dept_name, dept_manager
emp_manager
是 employee(emp_id)
的外键
emp_dept
是 department(dept_id)
的外键
dept_manager
是 employee(emp_id)
的外键
它可以这样工作:
CREATE TABLE employee (
emp_id int PRIMARY KEY
, emp_dept int NOT NULL
, emp_manager int
, emp_name text NOT NULL
, CONSTRAINT fk_emp_manager FOREIGN KEY (emp_manager) REFERENCES employee(emp_id)
, UNIQUE (emp_dept, emp_id) -- needed for FK fk_dept_manager
);
CREATE TABLE department (
dept_id int PRIMARY KEY
, dept_manager int
, dept_name text NOT NULL
, CONSTRAINT fk_dept_manager FOREIGN KEY (dept_id, dept_manager) REFERENCES employee(emp_dept, emp_id)
);
ALTER TABLE employee
ADD CONSTRAINT fk_emp_dept
FOREIGN KEY (emp_dept) REFERENCES department(dept_id);
请注意我如何将 fk_dept_manager
更改为多列 FK 引用以仅允许同一部门的员工成为部门经理。假设你想要那个。
您可能还需要 table employee
中的 CHECK
约束来禁止员工成为他们自己的经理:
CHECK (emp_manager <> emp_id)
如何INSERT
?
像往常一样。为了克服相互依赖性,要么在单个事务中设置 FK 约束 DEFERRABLE
和 运行 多个命令(成本更高),要么使用具有一个或多个 CTE 的单个命令。
示例:同时插入一个新部门和一个新员工作为其经理:
WITH ins_dept AS (
INSERT INTO department
(dept_manager , dept_name)
VALUES (nextval(pg_get_serial_sequence('employee', 'emp_id')), 'Sales')
RETURNING *
)
INSERT INTO employee
(emp_id , emp_dept, emp_manager, emp_name)
SELECT dept_manager, dept_id , NULL, 'Bob'
FROM ins_dept;
db<>fiddle here
进一步阅读:
- Complex foreign key constraint in SQLAlchemy
- How to deal with mutually dependent inserts
如何在 PostgreSQL 中创建行并将其插入到以下 table 模式:
Table: employee
emp_id, emp_name, emp_dept, emp_manager
Table: department
dept_id, dept_name, dept_manager
emp_manager
是 employee(emp_id)
emp_dept
是 department(dept_id)
dept_manager
是 employee(emp_id)
它可以这样工作:
CREATE TABLE employee (
emp_id int PRIMARY KEY
, emp_dept int NOT NULL
, emp_manager int
, emp_name text NOT NULL
, CONSTRAINT fk_emp_manager FOREIGN KEY (emp_manager) REFERENCES employee(emp_id)
, UNIQUE (emp_dept, emp_id) -- needed for FK fk_dept_manager
);
CREATE TABLE department (
dept_id int PRIMARY KEY
, dept_manager int
, dept_name text NOT NULL
, CONSTRAINT fk_dept_manager FOREIGN KEY (dept_id, dept_manager) REFERENCES employee(emp_dept, emp_id)
);
ALTER TABLE employee
ADD CONSTRAINT fk_emp_dept
FOREIGN KEY (emp_dept) REFERENCES department(dept_id);
请注意我如何将 fk_dept_manager
更改为多列 FK 引用以仅允许同一部门的员工成为部门经理。假设你想要那个。
您可能还需要 table employee
中的 CHECK
约束来禁止员工成为他们自己的经理:
CHECK (emp_manager <> emp_id)
如何INSERT
?
像往常一样。为了克服相互依赖性,要么在单个事务中设置 FK 约束 DEFERRABLE
和 运行 多个命令(成本更高),要么使用具有一个或多个 CTE 的单个命令。
示例:同时插入一个新部门和一个新员工作为其经理:
WITH ins_dept AS (
INSERT INTO department
(dept_manager , dept_name)
VALUES (nextval(pg_get_serial_sequence('employee', 'emp_id')), 'Sales')
RETURNING *
)
INSERT INTO employee
(emp_id , emp_dept, emp_manager, emp_name)
SELECT dept_manager, dept_id , NULL, 'Bob'
FROM ins_dept;
db<>fiddle here
进一步阅读:
- Complex foreign key constraint in SQLAlchemy
- How to deal with mutually dependent inserts