外键在 MySQL 中不起作用:为什么我可以插入不在外键列中的值?

2024-02-14

我在 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 仍然允许这些值。

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

UPDATE 1

如果我添加TYPE=InnoDB到最后,我得到一个错误:

错误 1005 (HY000): 无法创建表 './quotes/actions.frm' (errno: 150)

为什么会发生这种情况?

UPDATE 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 犯了一个很大的错误silently忽略外键约束声明。没有错误或警告表明存储引擎不支持它们。

MySQL 8.0.16之前的CHECK约束也是如此。 MySQL 使用的存储引擎均不支持 CHECK 约束,但 SQL 解析器毫无怨言地接受它们。在8.0.16及更高版本中,InnoDB表确实支持CHECK约束,但其他存储引擎仍然忽略它们。


当无法创建 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 比 MyISAM 性能更好 http://www.mysqlperformanceblog.com/2007/01/08/innodb-vs-myisam-vs-falcon-benchmarks-part-1/(虽然InnoDB需要更多关注调整配置 http://www.mysqlperformanceblog.com/2006/09/29/what-to-tune-in-mysql-server-after-installation/),InnoDB 支持原子更改、事务、外键,并且 InnoDB 更能抵抗崩溃中损坏的数据。

除非您运行的是旧的、不受支持的 MySQL 版本(5.0 或更早版本),否则您应该使用 InnoDB 作为您的数据库。default存储引擎选择,并且仅当您可以演示可以从 MyISAM 受益的特定工作负载时才使用 MyISAM。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

外键在 MySQL 中不起作用:为什么我可以插入不在外键列中的值? 的相关文章

  • PHP Microsoft Excel 文件生成/导出类

    我一直在寻找一个好的 Excel 文件生成类 但还没有找到 我的首要问题是 虽然我可以在 Excel 中打开导出的文件 运行 2007 年 但我总是收到一条警告 文件的格式与文件扩展名不同 我注意到 phpMyAdmin 中的 Excel
  • BIT(1) 的存储大小是多少?

    我一直认为a的存储大小BIT 1 列为 1 位 But http dev mysql com doc refman 5 6 en storage requirements html http dev mysql com doc refman
  • 如何在 Node 中使用 Mysql2 使用 async 和 pool 获取 MySQL 的 insertId?

    我正在尝试将 async wait 与 mysql2 和池一起使用 但我认为我做错了 下面是我的代码 正如我所说 我不确定我是否在这里做事 const pool mysql createPool host localhost user ro
  • Mysql 更快的 INSERT

    好的 我有大约 175k 个 INSERT 语句 相当大的 INSERT 语句 例如 INSERT INTO gast ID Identiteitskaartnummer Naam Voornaam Adres Postcode Stad
  • 如何从 mysqldump 中删除表

    如何删除 mysqldump 中包含大量表的一个大表的输出 我有一个 6 GB 大的数据库转储 但其中 90 只是一个日志记录表 cache entries 我的备份中不再需要它 如何轻松删除转储中描述大型日志记录表的部分 我找到了这个 h
  • PHP中如何检查输入类型按钮是否被按下?

    isset 函数可用于检查输入类型submit被按下 但是有没有办法检查输入类型按钮是否被按下 在我的代码中 按钮什么也不做 只是在 Onclick 事件上调用一个函数 然后刷新页面并在 PHP 中创建数据库条目 并且我希望它仅在按下按钮后
  • 当按第三个分组时,MySQL 根据另一个字段的最小值更新字段

    我已经阅读了几个关于选择最小值 分组等的线程 但似乎无法创建有效的查询来解决这个问题 如有重复 敬请原谅 我有一个像这样的表 ID Date Value Tag 1 1 1 13 500 NULL 2 1 1 13 10 NULL 3 1
  • 创建 MySQL 用户时使用 % 表示主机

    我的 MySQL 数据库需要两个用户 appuser 和 support 一位应用程序开发人员坚持要求我为这些用户创建四个帐户 appuser appuser localhost support support localhost 我一生都
  • 在 PHP / MySQL 中处理未读帖子

    对于个人项目 我需要使用 PHP 和 MySQL 构建一个论坛 我不可能使用已经构建的论坛包 例如phpBB 我目前正在研究构建此类应用程序所需的逻辑 但这已经是漫长的一天了 我正在努力解决为用户处理未读帖子的概念 我的一个解决方案是有一个
  • 如何在 mySQL 中定义自定义 ORDER BY 顺序

    在 MySQL 中如何定义自定义排序顺序 为了尝试解释我想要的内容 请考虑这张表 ID Language Text 0 ENU a 0 JPN b 0 DAN c 1 ENU d 1 JPN e 1 DAN f 2 etc 在这里 我想返回
  • 如何列出允许登录mysql的ip?

    我知道使用下面的命令 可以允许远程IP登录MySQL GRANT select insert update delete ON TO root my ip IDENTIFIED BY my password FLUSH PRIVILEGES
  • MAMP Pro mysql 无法启动

    我遇到问题无法找到解决此问题的方法 我收到这个错误 2017 01 11 23 58 25 7fffbac563c0 InnoDB Operating system error number 2 in a file operation In
  • mysql查询where条件比较char字段与int 0的一些现象

    有一桌 root localhost test 05 35 05 gt desc t Field Type Null Key Default Extra id int 11 NO PRI NULL auto increment studio
  • 使用 MYSQL 创建随机数

    我想知道是否有一种方法可以选择 100 到 500 之间随机生成的数字以及选择查询 Eg SELECT name address random number FROM users 我不必将此数字存储在数据库中 而只需使用它来显示目的 我尝试
  • 使用每个单独行的多个“where”子句更新多行

    我正在尝试像这样更新我的表 Update MyTable SET value 1 WHERE game id 1 x 4 y 8 SET value 2 WHERE game id 1 x 3 y 7 SET value 3 WHERE g
  • mysql 修改全文搜索的停用词列表

    我搜索了很多 据说我必须编辑 my cnf 文件来更改停用词列表 我将 my medium cnf 重命名为 my cnf 并添加了 ft query expansion limit 和 ft stopword file 条件 我已经重新启
  • python - _mysql 无法打开包含文件:'config-win.h':安装 mysql-python 时没有这样的文件或目录

    我试图安装两个名为 mysql python 和 mysqlclient fork of mysql python 的 python 库 然后当我尝试使用 pip 安装它时出现此错误 Collecting mysql python Usin
  • 为什么 MySQL 将 é 与 e 视为相同?

    我使用 Django Web 应用程序将 Unicode 字符串存储在 MySQL 数据库中 我可以很好地存储 Unicode 数据 但是在查询时 我发现 and e被视为好像它们是同一个角色 In 1 User objects filte
  • 提高mysql导入速度[关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我有一个很大的数据库22GB 我曾经用过进行备份mysqldumpgzip 格式的命令 当我提取 gz 文件时 它会生成 sql文件的
  • mysql - 有什么方法可以帮助使用另一个索引进行全文搜索?

    假设我有一个 文章 表 其中包含以下列 article text fulltext indexed author id indexed 现在我想搜索特定作者撰写的文章中出现的术语 所以像这样 select from articles whe

随机推荐