mysql - 外键在MySQL中不起作用:为什么我要插入外列中没有的值?

标签 mysql foreign-keys innodb mysql-error-1005

我在MySQL中创建了一个表:

CREATE TABLE actions ( A_id int NOT NULL AUTO_INCREMENT,
type ENUM('rate','report','submit','edit','delete') NOT NULL,
Q_id int NOT NULL,
U_id int NOT NULL,
date DATE NOT NULL,
time TIME NOT NULL,
rate tinyint(1),
PRIMARY KEY (A_id),
CONSTRAINT fk_Question FOREIGN KEY (Q_id) REFERENCES questions(P_id),
CONSTRAINT fk_User FOREIGN KEY (U_id) REFERENCES users(P_id));


这样就创建了我想要的表(尽管“ DESCRIBE actions;”命令向我显示外键是MUL类型的键,但我不确定这是什么意思)。但是,当我尝试输入问题或用户表中不存在的Q_id或U_id时,MySQL仍然允许这些值。

我做错了什么?如何防止带有外键的表接受无效数据?

更新1

如果将TYPE=InnoDB添加到末尾,则会出现错误:


  错误1005(HY000):无法创建表“ ./quotes/actions.frm”(错误号:150)


为什么会发生这种情况?

更新2

有人告诉我,使用功能性外键强制数据完整性很重要,而且InnoDB不应与MySQL一起使用。你有什么建议吗?

最佳答案

我猜您的默认存储引擎是MyISAM,它会忽略外键约束。它静默接受外键的声明,但不存储约束或随后强制执行约束。

但是,它确实在为外键声明的列上隐式创建索引。在MySQL中,“ KEY”是“ INDEX”的同义词。这就是DESCRIBE输出中显示的内容:索引,但不是约束。

您现在可以将无效值插入表中,因为没有约束。要获得强制实施参照完整性的约束,必须使用InnoDB存储引擎:

CREATE TABLE actions (
  A_id int NOT NULL AUTO_INCREMENT,
  ...
  CONSTRAINT fk_Question FOREIGN KEY (Q_id) REFERENCES questions(P_id),
  CONSTRAINT fk_User FOREIGN KEY (U_id) REFERENCES users(P_id)
) ENGINE=InnoDB;


我一直认为,默默地忽略外键约束声明是MySQL的一个大错误。没有错误或警告,表明存储引擎不支持它们。

CHECK约束也是如此。顺便说一句,没有与MySQL一起使用的存储引擎支持CHECK约束,但是SQL解析器毫无保留地接受它们。



当无法创建InnoDB表时,会出现errno 150问题,因为它无法理解外键约束。您可以通过以下方式获得更多信息:

SHOW ENGINE INNODB STATUS;


InnoDB外键的一些要求:


被引用的表也必须是InnoDB。
被引用的表必须具有索引和主键。
FK列和引用的PK列的SQL数据类型必须相同。例如,INT与BIGINT或INT UNSIGNED不匹配。




您可以更改其中包含数据的表的存储引擎:

ALTER TABLE actions ENGINE=InnoDB;


这样可以有效地将整个MyISAM表复制到InnoDB表,然后成功将其删除MyISAM表,并将新的InnoDB表重命名为以前的MyISAM表的名称。这称为“表重组”,它可能很耗时,具体取决于表中的数据量。在ALTER TABLE期间会进行表重组,即使在某些情况下似乎不必要。



重新更新2:


  有人告诉我,使用功能性外键加强数据完整性很重要,而且InnoDB不应与MySQL一起使用。你有什么建议吗?


谁告诉你的?这是绝对错误的。 InnoDB has better performance than MyISAM(尽管InnoDB需要更多地关注tuning the configuration),但InnoDB支持原子更改,事务,外键,并且InnoDB更能抵抗崩溃中的数据损坏。

除非您正在运行不受支持的旧版本MySQL(5.0或更早版本),否则应将InnoDB用作默认存储引擎选择,并且仅在可以证明受益于MyISAM的特定工作负载时才使用MyISAM。

关于mysql - 外键在MySQL中不起作用:为什么我要插入外列中没有的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54641905/

相关文章:

InnoDB 表不显示 MySQL FK 字段

mysql - 多选复选框sql设计

mysql - 如果字符串与 MYSQL 列表之一匹配,则返回 bool 值

mysql - SQL Select 语句被一个变量关闭但找不到问题

java - 无法存储包含特殊字符的消息

mysql - 来自 information_schema 的约束细节(关于更新级联,关于删除限制)

php - 这会存储在页面上吗?

mysql - 将自引用数据插入复制表

java - MySQLIntegrityConstraintViolationException : Cannot add or update a child row

php - MySQL 的最佳配置? InnoDB 和 MyISAM