【问题标题】:MYSQL ERROR 1452 A foriegn key constraint failsMYSQL ERROR 1452 外键约束失败
【发布时间】:2017-11-19 00:07:20
【问题描述】:

我有一个运行良好的注册表单,但由于某种原因它没有添加到数据库中。所以我在 phpmyadmin 中测试了这个查询,我发现了这个错误

查询:

INSERT INTO `EMTS`(`name`, `nickname`, `age`, `number`, `city`, `password`, `street`, `building`) 
VALUES ("Alice","Aa","21","414514151","New York","111","main","x")

我没有故意填写其他列。在其他数据库中这不会导致任何问题

错误:

#1452 - 无法添加或更新子行:外键约束失败 (mydb.emts, CONSTRAINT fk_EMTS_shifts1 FOREIGN KEY (shifts_idshifts) REFERENCES shifts (idshifts) ON DELETE更新时不采取行动不采取行动)

这是 emts 表:

CREATE TABLE IF NOT EXISTS mydb.EMTS(
idEMTS INT NOT NULL AUTO_INCREMENT,
name VARCHAR(45) NOT NULL,
nickname VARCHAR(45) NOT NULL,
age VARCHAR(45) NOT NULL,
number VARCHAR(45) NOT NULL,
email VARCHAR(45) NOT NULL,
city VARCHAR(255) NOT NULL,
password VARCHAR(45) NOT NULL,
shifts_idshifts INT(45) NOT NULL,
bloodtype_id INT NOT NULL,
street VARCHAR(45) NOT NULL,
building VARCHAR(45) NOT NULL,
  PRIMARY KEY (idEMTS),
  INDEX fk_EMTS_shifts1_idx(shifts_idshifts ASC),
  INDEX fk_EMTS_bloodtype1_idx(bloodtype_id ASC),
  UNIQUE INDEX nickname_UNIQUE(nickname ASC),
  CONSTRAINT fk_EMTS_shifts1
    FOREIGN KEY (shifts_idshifts)
    REFERENCES mydb.shifts(idshifts)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT fk_EMTS_bloodtype1
    FOREIGN KEY (bloodtype_id)
    REFERENCES mydb.bloodtype(id)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

这是血型表:

CREATE TABLE IF NOT EXISTS mydb.bloodtype(
type INT NOT NULL,
id INT NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (id))
ENGINE = InnoDB;

这是班次表:

CREATE TABLE IF NOT EXISTS mydb.shifts(
startdate INT NOT NULL,
enddate VARCHAR(45) NOT NULL,
day VARCHAR(45) NOT NULL,
idshifts INT NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (idshifts))
ENGINE = InnoDB;

我不明白怎么了?

【问题讨论】:

  • 你的答案就在那里,需要填写shifts_idshifts而你没有填写。
  • 这是 SQL Server 还是 MySQL?

标签: php mysql database


【解决方案1】:

我在本地 MySQL 实例上测试了您的查询。

如您所述,您没有为外键列提供值。但它们不是 NULL 列,并且它们没有默认值。所以MySQL填入值0。

我通过删除 FOREIGN KEY 约束并再次尝试 INSERT 来证明这一点:

mysql> INSERT INTO `EMTS`(`name`, `nickname`, `age`, `number`, `city`, `password`, `street`, `building`) 
    -> VALUES ("Alice","Aa","21","414514151","New York","111","main","x");
Query OK, 1 row affected, 3 warnings (0.02 sec)

mysql> show warnings;
+---------+------+------------------------------------------------------+
| Level   | Code | Message                                              |
+---------+------+------------------------------------------------------+
| Warning | 1364 | Field 'email' doesn't have a default value           |
| Warning | 1364 | Field 'shifts_idshifts' doesn't have a default value |
| Warning | 1364 | Field 'bloodtype_id' doesn't have a default value    |
+---------+------+------------------------------------------------------+
3 rows in set (0.01 sec)

mysql> select * from EMTS;
+--------+-------+----------+-----+-----------+-------+----------+----------+-----------------+--------------+--------+----------+
| idEMTS | name  | nickname | age | number    | email | city     | password | shifts_idshifts | bloodtype_id | street | building |
+--------+-------+----------+-----+-----------+-------+----------+----------+-----------------+--------------+--------+----------+
|      3 | Alice | Aa       | 21  | 414514151 |       | New York | 111      |               0 |            0 | main   | x        |
+--------+-------+----------+-----+-----------+-------+----------+----------+-----------------+--------------+--------+----------+

注意两个外键列的值都是 0。

如果您不想为外键列提供值,请将它们设为可为空的列。 NULL 可以存在,它不会导致违反外键约束。而 0 是一个非 NULL 值,但它不存在于所引用的班次和血型表中。

https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html 说:

对于没有显式 DEFAULT 的 NOT NULL 列的数据输入 子句,如果 INSERT 或 REPLACE 语句不包含 列,或 UPDATE 语句将列设置为 NULL,MySQL 处理 根据当时有效的SQL模式的列:

  • 如果启用严格的 SQL 模式,事务处理会出错 表和语句被回滚。对于非事务表, 发生错误,但如果第二行或后续行发生这种情况 对于多行语句,前面的行将是 插入。

  • 如果未启用严格模式,MySQL 会将列设置为隐式 列数据类型的默认值。

整数列的隐式默认值为 0。

这是 MySQL 的一种奇怪行为,导致许多开发人员感到困惑。如果该列不是 NULL,那么为什么它允许我们插入 NULL,并默认为一些未指定的隐式默认值?这是违反直觉的。

因此,在 MySQL 5.7 及更高版本的较新版本中,严格模式已成为默认模式。你也可以自己设置严格模式:

mysql> SET sql_mode='strict_all_tables';

mysql> INSERT INTO `EMTS`(`name`, `nickname`, `age`, `number`, `city`, `password`, `street`, `building`) 
    -> VALUES ("Alice","Aa","21","414514151","New York","111","main","x");
ERROR 1364 (HY000): Field 'email' doesn't have a default value

【讨论】:

  • 但是我可以稍后更新空对象吗?例如,当我要填充表血型时,我将在血型表主键(id)的值中插入血型 ID 外键。对不起,我是 sql 新手
  • 是的,您可以为允许 NULL 的列插入 NULL(但如果该列被声明为 NOT NULL,就像您的一样)。然后您可以稍后使用UPDATE 为该行赋予一个满足外键的值。
猜你喜欢
  • 2013-11-17
  • 1970-01-01
  • 2013-05-03
相关资源
最近更新 更多