【问题标题】:Cannot enter data into tables with inter related foreign keys无法将数据输入到具有相互关联的外键的表中
【发布时间】:2020-05-04 06:33:33
【问题描述】:

我使用以下代码创建了表,但外键约束不允许添加数据。我该怎么做才能解决这个问题?

CREATE TABLE Employee(
Ssn VARCHAR(10) PRIMARY KEY NOT NULL,
BDate DATE,
FName VARCHAR(25),
MInit VARCHAR(5),
LName VARCHAR(25),
Address VARCHAR(40),
Sex VARCHAR(6),
Salary INT,
SupervisorSsn VARCHAR(10),
DNumber INT
);
CREATE TABLE

CREATE TABLE Department(
DNumber INT PRIMARY KEY NOT NULL,
DName VARCHAR(15),
MgrSsn VARCHAR(10),
MgrStartDate DATE,
NumberofEmployees INT,
CONSTRAINT Department_MgrSsn_FK FOREIGN KEY(MgrSsn) REFERENCES Employee(Ssn) ON DELETE SET DEFAULT ON UPDATE CASCADE
);

ALTER TABLE Employee
ADD CONSTRAINT Employee_SupervisorSsn_FK FOREIGN KEY(SupervisorSsn) REFERENCES Employee(Ssn) ON DELETE SET DEFAULT ON UPDATE CASCADE,
ADD CONSTRAINT Employee_DNumber_FK FOREIGN KEY(DNumber) REFERENCES Department(DNumber) ON DELETE SET DEFAULT ON UPDATE CASCADE;

【问题讨论】:

  • 为什么不允许插入行? dbfiddle.uk/…
  • 由于相互关联的外键约束
  • 不确定您的意思,插入工作正常:dbfiddle.uk/…
  • 但是您没有为外键输入数据,对吧?例如Employee中的DNumber

标签: postgresql foreign-keys sql-insert


【解决方案1】:

在 Postgres 中有几种方法可以做到这一点。

稍后更新

最明显的一个:先插入null值,然后再更新:

insert into department 
  (dnumber, dname)
values 
  (1, 'One'),
  (2, 'Two'),
  (3, 'Three');

insert into employee (ssn, fname, lname, supervisorssn, dnumber)
values 
  ('123', 'Arthur', 'Dent', '456', 1),
  ('456', 'Ford', 'Prefect', null, 2),
  ('789', 'Zaphod', 'Beeblebrox', null, 3);

update department
  set mgrssn = '456'
where dnumber in (1,2);

update department
  set mgrssn = '789'
where dnumber = 3;

Online example

延迟约束

延迟约束,以便在事务结束时检查它们,而不是在运行 INSERT 时检查:

ALTER TABLE department
  add constraint fk_dempt2emp foreign key (mgrssn) references employee
  deferrable initially deferred; --<<

然后你可以按照你喜欢的任何顺序插入行,只要所有事情都发生在一个事务中:

begin transaction; --<< important!

insert into department 
  (dnumber, dname, mgrssn)
values 
  (1, 'One', '456'),
  (2, 'Two', '456'),
  (3, 'Three', '789')

insert into employee (ssn, fname, lname, supervisorssn, dnumber)
values 
  ('123', 'Arthur', 'Dent', '456', 1),
  ('456', 'Ford', 'Prefect', null, 2),
  ('789', 'Zaphod', 'Beeblebrox', null, 3);

commit; -- the FKs will be checked here

在一个语句中完成所有操作

您可以使用data modifying CTE 将行插入两个表中。由于这是作为单个语句评估的,因此约束不需要是可延迟的。

with new_depts as (
  insert into department 
    (dnumber, dname, mgrssn)
  values 
    (1, 'One', '456'),
    (2, 'Two', '456'),
    (3, 'Three', '789')
)
insert into employee (ssn, fname, lname, supervisorssn, dnumber)
values 
  ('123', 'Arthur', 'Dent', '456', 1),
  ('456', 'Ford', 'Prefect', null, 2),
  ('789', 'Zaphod', 'Beeblebrox', null, 3)
;

Online example

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-09
    • 2017-01-10
    • 2011-07-20
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    相关资源
    最近更新 更多