【问题标题】:MySQL Incorrect Foreign Key [closed]MySQL不正确的外键[关闭]
【发布时间】:2020-06-28 17:03:06
【问题描述】:

MySQL (mariadb Ver 15.1 Distrib 10.1.44-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2) 给了我这个错误: ERROR 1005 (HY000) at line 129: Can't create table `Houdini`.`stamp` (errno: 150 "Foreign key constraint is incorrectly formed")

尝试创建此表时:

DROP TABLE IF EXISTS stamp;
CREATE TABLE stamp (
  id INT NOT NULL,
  name VARCHAR(50) NOT NULL,
  group_id SMALLINT NOT NULL,
  member BOOLEAN NOT NULL DEFAULT FALSE,
  rank SMALLINT NOT NULL DEFAULT 1,
  description VARCHAR(255) NOT NULL DEFAULT '',
  PRIMARY KEY(id),
  CONSTRAINT stamp_ibfk_1 FOREIGN KEY (group_id) REFERENCES stamp_group (id) ON DELETE CASCADE ON UPDATE CASCADE
); 

什么是正确的外键约束?我想group_id 由于某种原因不能使用

【问题讨论】:

  • 在这个表中,主键外键 NO。 PK 是复合的,而每个 FK 表达式是单一的。
  • (显然,)这是一个常见问题解答。请在考虑发布之前阅读您的教科书和/或手册和谷歌任何错误消息或您的问题/问题/目标的许多清晰、简洁和精确的措辞,有和没有您的特定字符串/名称和站点:stackoverflow.com 和标签;阅读许多答案。如果您发布问题,请使用一个短语作为标题。反映你的研究。请参阅How to Ask 和投票箭头鼠标悬停文本。 PS你有一个语法错误。阅读语法和手册。显示组成子表达式是好的。删除留下错误的代码。
  • 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 暂停整体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。
  • "在这个表中,主键是外键..." -- 不是。外键是列集(每个表一个) ,而不仅仅是一组列。

标签: sql foreign-keys mariadb


【解决方案1】:

外键是quest_award_item 表的主键的成员,因此它们必须是与自身相同的数据类型,但这不是问题。

您似乎认为它们必须具有与自己表的主键相同的数据类型,但这实际上不是必需的。 要求是外键列必须与它们引用的列具有相同的数据类型。

在这种情况下,quest_award_item.quest_id 的数据类型必须与 quest.id 相同。

同样,quest_award_item.item_id 的数据类型必须与 item.id 相同。

您没有显示questitem 表的表定义,因此我们只能猜测它们的数据类型。但是其中一个或另一个可能具有不兼容的数据类型。


你的评论:

那么我该如何解决这个问题?

您在下面的评论中发布了quest.id 列定义为SERIAL,MySQL 将其转换为BIGINT UNSIGNED AUTO_INCREMENT

引用quest.id 的外键列必须与它引用的列具有相同的数据类型(AUTO_INCREMENT 部分不必匹配数据类型)。

所以改变你的 CREATE TABLE:

CREATE TABLE quest_award_item (
  quest_id BIGINT UNSIGNED NOT NULL,
  item_id INT NOT NULL,
  PRIMARY KEY (quest_id, item_id),
  CONSTRAINT quest_award_item_ibfk_1 FOREIGN KEY (quest_id) REFERENCES quest (id) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT quest_award_item_ibfk_2 FOREIGN KEY (item_id) REFERENCES item (id) ON DELETE CASCADE ON UPDATE CASCADE
);

另一种解决方案是将quest.id 修改为INT,然后您原来的CREATE TABLE quest_award_item 将起作用。

ALTER TABLE quest MODIFY COLUMN id INT AUTO_INCREMENT;

但是,如果您在该表中已经有 id 值足够大以至于它们需要为 BIGINT UNSIGNED(即大于 231-1)的行,那么您不能这样做。

【讨论】:

  • 删除表如果存在任务; CREATE TABLE quest (id SERIAL, name VARCHAR(30) NOT NULL, PRIMARY KEY(id));
  • 如果项目存在则删除表; CREATE TABLE 项目 (id INT NOT NULL, name VARCHAR(50), PRIMARY KEY (id));
  • SERIAL 变为 BIGINT UNSIGNED,与您的 INT 外键不兼容。
  • 那么我该如何解决这个问题?
【解决方案2】:

可能是两个key之间的数据类型不一样

DROP TABLE IF EXISTS stamp;
CREATE TABLE stamp (
  id INT NOT NULL,
  name VARCHAR(50) NOT NULL,
  group_id INT NOT NULL,
  member BOOLEAN NOT NULL DEFAULT FALSE,
  rank SMALLINT NOT NULL DEFAULT 1,
  description VARCHAR(255) NOT NULL DEFAULT '',
  PRIMARY KEY(id),
  CONSTRAINT stamp_ibfk_1 FOREIGN KEY (group_id) REFERENCES stamp_group (id) ON DELETE CASCADE ON UPDATE CASCADE
); 

如果你使用 int 作为 id 你应该使用 int 作为 group_id

【讨论】:

    猜你喜欢
    • 2017-05-29
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 2018-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多