DROP TABLE IF EXISTS - 无法删除或更新父行:外键约束失败

DROP TABLE IF EXISTS - Cannot delete or update a parent row: a foreign key constraint fails



我正在尝试为医院创建一个数据库,其中包含 Patient、Ward 等表格。 但是,当我执行 SQL 脚本时,出现以下错误。 我该如何解决这个错误?

删除 TABLE 如果存在员工 |错误代码:1217。无法删除或更新父行:外键约束失败

当我注释掉 DROP TABLE IF EXISTS Staff 时,我得到了这个错误:

我的 SQL 脚本如下。
非常感谢。

USE test;

DROP TABLE IF EXISTS Ward;
DROP TABLE IF EXISTS PatientWard;
DROP TABLE IF EXISTS Patient;
DROP TABLE IF EXISTS NextOfKin;
DROP TABLE IF EXISTS NextOfKinTelephone;
DROP TABLE IF EXISTS Medication;
DROP TABLE IF EXISTS Prescription;
DROP TABLE IF EXISTS Staff;
DROP TABLE IF EXISTS StaffPatient;
DROP TABLE IF EXISTS Hospital;
DROP TABLE IF EXISTS HospitalTelephone;

CREATE TABLE Ward(
wardID INT(5) NOT NULL AUTO_INCREMENT,
hospitalID INT(5) default 0,
name VARCHAR(100) NOT NULL,
specialism VARCHAR(50) NOT NULL,
PRIMARY KEY(wardID),
FOREIGN KEY(hospitalID) REFERENCES Hospital(hospitalID) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX name(name)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE PatientWard(
wardID INT(5) NOT NULL,
nationalInsuranceNo VARCHAR(20) default 0,
dateOfAdmission date NOT NULL,
note VARCHAR(250),
PRIMARY KEY(wardID, nationalInsuranceNo, dateOfAdmission),
FOREIGN KEY(wardID) REFERENCES Ward(wardID) ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY(nationalInsuranceNo) REFERENCES Patient(nationalInsuranceNo) ON DELETE RESTRICT ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE Patient(
nationalInsuranceNo VARCHAR(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
dateOfBirth date NOT NULL,
sex VARCHAR(20) NOT NULL,
PRIMARY KEY(nationalInsuranceNo),
INDEX name(name)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE NextOfKin(
nextOfKinID INT(5) NOT NULL AUTO_INCREMENT,
nationalInsuranceNo VARCHAR(20) default 0,
name VARCHAR(100) NOT NULL,
PRIMARY KEY(nextOfKinID),
FOREIGN KEY(nationalInsuranceNo) REFERENCES Patient(nationalInsuranceNo) ON DELETE CASCADE ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE NextOfKinTelephone(
nextOfKinID INT(5) default 0,
telephoneNumber VARCHAR(14) NOT NULL,
PRIMARY KEY(nextOfKinID, telephoneNumber),
FOREIGN KEY(nextOfKinID) REFERENCES NextOfKin(nextOfKinID) ON DELETE CASCADE ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE Medication(
NHS_ID INT(5) NOT NULL AUTO_INCREMENT,
hospitalID INT(5) default 0,
name VARCHAR(100) NOT NULL,
contraindications VARCHAR(200) NOT NULL,
PRIMARY KEY(NHS_ID),
FOREIGN KEY(hospitalID) REFERENCES Hospital(hospitalID) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX name(name),
INDEX contraindications(contraindications)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE Prescription(
prescriptionID INT(5) NOT NULL AUTO_INCREMENT,
staffID INT(5) default 0,
NHS_ID INT(5) default 0,
nationalInsuranceNo INT(5) default 0,
startDate date NOT NULL,
dose VARCHAR(30) NOT NULL,
frequencyOfAdministration VARCHAR(100) NOT NULL,
endDate date NOT NULL,
PRIMARY KEY(prescriptionID),
FOREIGN KEY(staffID) REFERENCES Staff(staffID) ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY(NHS_ID) REFERENCES Medication(NHS_ID) ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY(nationalInsuranceNo) REFERENCES Patient(nationalInsuranceNo) ON DELETE RESTRICT ON UPDATE CASCADE,
INDEX startDate(startDate)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE Staff(
staffID INT(5) NOT NULL AUTO_INCREMENT,
hospitalID INT(5),
forename VARCHAR(50) NOT NULL,
surname VARCHAR(50) NOT NULL,
salary DECIMAL(6,2) NOT NULL,
position VARCHAR(50) NOT NULL,
PRIMARY KEY(staffID),
FOREIGN KEY(hospitalID) REFERENCES Hospital(hospitalID) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX salary(salary)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE StaffPatient(
staffID INT(5) default 0,
nationalInsuranceNo INT(5) default 0,
PRIMARY KEY(staffID, nationalInsuranceNo),
FOREIGN KEY(staffID) REFERENCES Staff(staffID) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY(nationalInsuranceNo) REFERENCES Patient(nationalInsuranceNo) ON DELETE CASCADE ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE Hospital(
hospitalID INT(5) NOT NULL AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
postcode VARCHAR(20) NOT NULL,
emailAddress VARCHAR(50) NOT NULL,
PRIMARY KEY(hospitalID)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE HospitalTelephone(
hospitalID INT(5) default 0,
telephoneNumber VARCHAR(14),
PRIMARY KEY(hospitalID, telephoneNumber),
FOREIGN KEY(hospitalID) REFERENCES Hospital(HospitalID) ON DELETE CASCADE ON UPDATE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

在删除您的 table 之前删除 FK。 还要在 table 之后创建 FK,这样你就可以给它一个明确的名称

IF EXISTS ( SELECT * FROM SYS.foreign_keys WHERE NAME = 'FK_Ward_Hospital' AND parent_object_id = OBJECT_ID('dbo.Ward'))
ALTER TABLE dbo.Ward DROP CONSTRAINT [FK_Ward_Hospital] 

DROP TABLE IF EXISTS Ward;

CREATE TABLE Ward
(
    wardID INT(5) NOT NULL AUTO_INCREMENT,    
    hospitalID INT(5) default 0,
    name VARCHAR(100) NOT NULL,
    specialism VARCHAR(50) NOT NULL,
    PRIMARY KEY(wardID),
    INDEX name(name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE [dbo].[Ward]  WITH CHECK ADD  CONSTRAINT [FK_Ward_Hospital] FOREIGN KEY([hospitalID])
REFERENCES [dbo].[Hospital] ([hospitalID])
ALTER TABLE [dbo].[Ward] CHECK CONSTRAINT [FK_Ward_Hospital]

错误消息告诉您由于父行有问题而无法删除 table。 (稍后将详细介绍 "problem" 的内容。)父行是另一个 table 中的一行,它引用了您要删除的 table 中的一行。例如,在 StaffPatient table 中你有 FOREIGN KEY(staffID) REFERENCES Staff(staffID)。因此,StaffPatient 中有 "parent rows" 引用了 Staff.

中的行

现在,对于从 StaffPatientStaff 的外键,您已经非常小心地指定了 ON DELETE CASCADE ON UPDATE CASCADE,这意味着当您从 Staff 父级删除行时StaffPatient 上的行也将被删除。到目前为止,还不错。

然而,在 Prescription table 中你有一个与 ON DELETE RESTRICT ON UPDATE CASCADE 相似的外键。 RESTRICT 关键字表示将阻止删除父行。因此,最有可能发生的情况是存在引用 Staff 行的处方行,从而防止您的 Staff table 被丢弃。

一个解决方案是在尝试删除 Staff table 之前删除 Prescription table。但是,理论上有可能进入循环级联情况,如果不采用 Chris Rodriguez 的答案中建议的解决方案,删除实际上是不可能的,即在删除 tables 之前删除所有外键。

之所以在这里发帖是因为我在这里找到了问题的答案:mysql drop table and cascade delete to all references to the table

我使用了这段代码,现在正在创建我的表。问题是我试图删除链接到具有外键的其他表的表。因此,通过禁用然后重新启用这些外键检查,可以创建我的表。

SET FOREIGN_KEY_CHECKS = 0;
drop table if exists <your_1st_table>;
drop table if exists <your_2nd_table>;
SET FOREIGN_KEY_CHECKS = 1;

编辑:您应该按照创建表格的相反顺序删除表格,这可能会解决您的问题。