简体   繁体   English

#1452-无法添加或更新子行:外键约束失败

[英]#1452 - Cannot add or update a child row: a foreign key constraint fails

I am trying to insert some data into the table User . 我试图将一些数据插入表User The User table has 2 foreign keys: StudentID and StaffID . User表具有2个外键: StudentIDStaffID

I want to be able to enter either StaffID or StudentID which should link to the relevant table(that already has either the StudentID or StaffID ). 我希望能够输入StaffIDStudentID ,它应该链接到相关的表(已经具有StudentIDStaffID )。 The table User can only have StaffID or StudentID . User只能具有StaffIDStudentID Can Anyone help? 有人可以帮忙吗?

INSERT INTO `User` (`UserName`, `Email`, `StudentID`,`StaffID`,`Paasword`) 
VALUES ('phill', 'ph@lms.com', '', '2201','654321');

Ok, so prepare yourself. 好,准备好自己 This answer is long, but thorough. 这个答案很长,但是很彻底。

Short Answer: 简短答案:

As referenced in this answer by @HLGEM you can accomplish what you're asking by making the primary keys in the STAFF and STUDENT table, presumably the values StaffID and StudentID NULLABLE . 正如@HLGEM在此答案中所引用的,您可以通过在STAFFSTUDENT表中设置主键(假定值StaffIDStudentID NULLABLE)来完成您要的内容。 Here is the relevant snippet from his answer: 以下是他的回答的相关摘要:

To allow nulls in an FK generally all you have to do is allow nulls on the field that has the FK. 要在FK中允许空值,通常要做的就是在具有FK的字段上允许空值。 The null value is separate from the idea of it being an FK. 空值与其作为FK的想法是分开的。

You can do this in your table definition adding NULL to your create statement similar to the following by specifying: 您可以在表定义中执行此操作,方法是指定以下内容,将NULL添加到create语句中,类似于以下内容:

CREATE TABLE STUDENT (
    StudentID INT UNSIGNED NULL PRIMARY KEY AUTO_INCREMENT
    ...
)

The above is an example of how to apply this to the STUDENT table. 以上是如何将其应用于STUDENT表的示例。 The STAFF table would have a similar approach. STAFF表将具有类似的方法。 Note, the extra values are there as a suggestion based on general configuration that is common when configuring ID fields. 请注意,这些额外的值是根据配置ID字段时常见的常规配置提供的建议。

LONG ANSWER: 长答案:

As @HLGEM mentioned in his answer, there are some times when it is appropriate to have a foreign key constraint that can be NULL . 正如@HLGEM在他的回答中提到的,在某些情况下,具有可以为NULL的外键约束是适当的。 However, in your case, it suggestions that the data is not fully normalized. 但是,根据您的情况,它建议数据未完全标准化。 The need for a NULL foreign key can be eliminated in your case with a little table refactoring. 在您的情况下,只需进行少量表重构即可消除对NULL外键的需要。 Let's explore an additional possibility when designing your database tables: 让我们探索设计数据库表时的另一种可能性:

Case Study: 案例分析:

Let's begin with the following assumption. 让我们从以下假设开始。 Since you said in your question: 由于您在问题中说过:

I want to be able to enter either StaffID or StudentID which should link to the relevant table(that already has either the StudentID or StaffID). 我希望能够输入StaffID或StudentID,它们应该链接到相关表(已经具有StudentID或StaffID)。 The table User can only have StaffID or StudentID 表用户只能具有StaffID或StudentID

It is probably a safe assumption to say that a user has to be a staff member or a student but not both. 可以肯定地说用户必须是工作人员 学生,不能同时是两者。 That assumption makes a strong use case for having a UserType table. 该假设为拥有UserType表提供了强有力的用例。 Let's alter the USER definition to support a UserTypeId and create the USER_TYPE table: 让我们更改USER定义以支持UserTypeId并创建USER_TYPE表:

# USER TYPE Table Definition
CREATE TABLE USER_TYPES (
  UserTypeId TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  UserType VARCHAR(25) NOT NULL
) ENGINE=INNODB CHARSET=UTF8;

# USER TABLE Definition
CREATE TABLE USERS (
  UserId INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  Name VARCHAR(25) NOT NULL,
  Email VARCHAR(50) NOT NULL,
  Password VARCHAR(100) NOT NULL,
  UserTypeId TINYINT UNSIGNED NOT NULL,
  FOREIGN KEY(UserTypeId) REFERENCES USER_TYPES(UserTypeId)
) ENGINE=INNODB CHARSET=UTF8;

Notice that in this new schema, we no longer have a reference to StudentID or StaffID , but instead we have a UserTypeId . 请注意,在此新架构中,我们不再引用StudentIDStaffID ,而是使用UserTypeId There are two benefits to this approach: 这种方法有两个好处:

  1. USERS . USERS UserTypeId is a foreign key reference to USER_TYPES . UserTypeId是对USER_TYPES的外键引用。 UserTypeId but no longer has to be NULLABLE . UserTypeId但不再必须为NULLABLE
  2. You can have more user types than just Student or Staff . 您不仅可以拥有StudentStaff还可以拥有更多的用户类型。

For our case study here, let's create two user types Student and Employee (I'll explain why I'm not using Staff here in a little). 对于这里的案例研究,让我们创建两个用户类型StudentEmployee (我将在这里解释为什么我不使用Staff原因)。 Let's also go ahead and populate the USERS table with the initial values for Phill , your employee you mentioned in your question. 我们还继续用您在问题中提到的员工Phill的初始值填充USERS表。

INSERT INTO USER_TYPES(UserType)
VALUES("Employee"),("Student");

INSERT INTO USERS(Name,Email,Password,UserTypeId)
VALUES("phill","ph@lms.com","654321",1);

Excellent! 优秀的! Our new design is coming together quickly. 我们的新设计很快就会融合在一起。 Now let's create two additional tables, one called STUDENTS and one called EMPLOYEES . 现在让我们创建另外两个表,一个称为STUDENTS ,另一个称为EMPLOYEES In this case, I chose to go with EMPLOYEES instead of STAFF because it allows you to be more flexible in how you define an employee . 在这种情况下,我选择使用EMPLOYEES而不是STAFF因为它使您在定义员工时更加灵活。 As you'll see in the definition, you can further define a user type of Employee with an ENUM value of either Faculty , Staff or Administrative . 在定义中将看到,您可以进一步定义Employee的用户类型,其ENUM值为FacultyStaffAdministrative Think of this as a subtype of the general type Employee . 将此视为一般类型Employee的子类型。 Note that you could also create another join table like we did for USER_TYPES , for instance one called EMPLOYEE_TYPES . 请注意,您还可以像为USER_TYPES那样创建另一个USER_TYPES表,例如一个名为EMPLOYEE_TYPES USER_TYPES表。 Either method is appropriate. 两种方法都合适。 I chose to use an ENUM instead of another foreign key to demonstrate an additional concept you could use if you only have a handful of choices. 我选择使用ENUM而不是另一个外键来演示如果您只有少数选择的话可以使用的其他概念。

So on to those last two table definitions: 接下来是最后两个表定义:

# STUDENTS Table Definition
CREATE TABLE STUDENTS(
  StudentId INT UNSIGNED PRIMARY KEY,
  Year ENUM('Freshman','Sophmore','Junior','Senior') NOT NULL,
  FOREIGN KEY(StudentId) REFERENCES USERS(UserId)
) ENGINE=INNODB CHARSET=UTF8;

# EMPLOYEES Table Definition
CREATE TABLE EMPLOYEES (
  EmployeeId INT UNSIGNED PRIMARY KEY,
  EmployeeType ENUM('Faculty','Staff','Administrative') NOT NULL,
  FOREIGN KEY(EmployeeId) REFERENCES USERS(UserId)
) ENGINE=INNODB CHARSET=UTF8;

Notice that these two tables do not have their own Id column, but instead, reference the Id from the USERS table as a foreign key constraint. 请注意,这两个表没有自己的Id列,而是将USERS表中的Id作为外键约束进行引用。 This makes sense because you have to be a user before you can be a student or an employee . 这是有道理的,因为您必须先成为用户,然后才能成为学生雇员

Finally, let's add some employee data for Phill : 最后,让我们为Phill添加一些员工数据:

INSERT INTO EMPLOYEES(EmployeeId,EmployeeType)
VALUES(1,"Faculty");

That was a lot, but now you'll begin to reap the benefits. 数量很多,但是现在您将开始获得好处。 Everything above was foundational in that it offers a fully normalized approach to your database layout with additional flexibility and without the need for a NULLABLE foreign key. 以上所有内容都是基础,因为它为您的数据库布局提供了完全标准化的方法,具有额外的灵活性,并且不需要NULLABLE外键。

Retrieving data in this instance is easy and we don't even have to know if Phill is an employee or a student . 在这种情况下,检索数据很容易,我们甚至不必知道Phill雇员还是学生 Let's look at an example query: 让我们看一个示例查询:

SELECT
u.UserId,
u.Name,
u.Email,
ut.UserType,
s.*,
e.*
FROM USERS AS u
INNER JOIN USER_TYPES AS ut ON u.UserTypeId = ut.UserTypeId
LEFT JOIN STUDENTS AS s ON u.UserId = s.StudentId
LEFT JOIN EMPLOYEES AS e ON u.UserId = e.EmployeeId
WHERE u.Email = "ph@lms.com";

which returns: 返回:

+--------+--------+-------------+-----------+-----------+--------+------------+--------------+
| UserId | Name   | Email       | UserType  | StudentId | Year   | EmployeeId | EmployeeType |
+--------+--------+-------------+-----------+-----------+--------+------------+--------------+
|      1 | phill  | ph@lms.com  | Employee  | (null)    | (null) |          1 | Faculty      |
+--------+--------+-------------+-----------+-----------+--------+------------+--------------+

Conclusion: 结论:

Live Example: sqlfiddle 实时示例: sqlfiddle

So there you have it. 所以你有它。 By performing a LEFT JOIN between STUDENTS , EMPLOYEES and the USERS table, you'll pull back all values that exist in either of the two tables and all the default user values. 通过在STUDENTSEMPLOYEESUSERS表之间执行LEFT JOIN ,您将拉回存在于两个表中的所有值以及所有默认用户值。 From here, it's a simple as checking for NULL on StudentId or EmployeeId to determine which user type you're working with. 从这里开始,很简单,只需检查StudentIdEmployeeId上的NULL即可确定您正在使用的用户类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 1452无法添加或更新子行:外键约束失败 - 1452 Cannot add or update a child row: a foreign key constraint fails #1452-无法添加或更新子行:外键约束失败 - #1452 - Cannot add or update a child row: a foreign key constraint fails #1452 - 无法添加或更新子行:外键约束失败 - #1452 - Cannot add or update a child row: a foreign key constraint fails #1452-无法添加或更新子行:外键约束失败3 - #1452 - Cannot add or update a child row: a foreign key constraint fails 3 1452 - 无法添加或更新子行:外键约束失败 - 1452 - Cannot add or update a child row: a foreign key constraint fails 错误1452:1452:无法添加或更新子行:外键约束失败 - ERROR 1452: 1452: Cannot add or update a child row: a foreign key constraint fails 错误:无法添加外键关系:#1452 - 无法添加或更新子行:外键约束失败 - Error: FOREIGN KEY relationship could not be added! #1452 - Cannot add or update a child row: a foreign key constraint fails SQLSTATE [23000]:违反完整性约束:1452无法添加或更新子行:外键约束失败 - SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails 违反完整性约束:1452无法添加或更新子行:外键约束失败 - Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails 违反完整性约束:1452无法添加或更新子行:外键约束失败 - Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM