【问题标题】:Error Code: 1822. Failed to add the foreign key constaint. Missing index for constraint错误代码:1822。添加外键约束失败。缺少约束索引
【发布时间】:2014-12-07 09:57:40
【问题描述】:

我发现了一些关于该错误的线索。但是所有的解决方案都不适合我。

我创建了 2 个表,一个用户表,一个用于文章。现在我想存储创建文章的用户和最后一个修饰符。

CREATE TABLE IF NOT EXISTS `testDb`.`users` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `nickname` VARCHAR(255) NULL,
  `first_name` VARCHAR(255) NULL,
  `last_name` VARCHAR(255) NULL,
  `e_mail` VARCHAR(255) NOT NULL,
  `activated` TINYINT(1) NOT NULL DEFAULT 0,
  `birth_date` DATE NULL,
  `locked` TINYINT(1) NOT NULL DEFAULT 0,
  `locked_date_time` DATETIME NULL,
  `street` VARCHAR(255) NULL,
  `street_number` VARCHAR(255) NULL,
  `city` VARCHAR(255) NULL,
  `postal_code` VARCHAR(255) NULL,
  `country` VARCHAR(255) NULL,
  `phone` VARCHAR(255) NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `user_id_UNIQUE` (`id` ASC)
)
ENGINE = InnoDB
AUTO_INCREMENT = 1;


CREATE TABLE IF NOT EXISTS `testDb`.`articles` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NULL,
  `description` VARCHAR(255) NULL,
  `create_user` INT ZEROFILL NOT NULL,
  `create_date_time` DATETIME NULL,
  `last_modifie_user` INT ZEROFILL NOT NULL,
  `last_modifie_date_time` DATETIME NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `article_id_UNIQUE` (`id` ASC),
  INDEX `fk_articles_users1_idx` (`create_user` ASC),
  INDEX `fk_articles_users2_idx` (`last_modifie_user` ASC)
)
ENGINE = InnoDB
AUTO_INCREMENT = 1;


ALTER TABLE `testDb`.`articles`
  ADD CONSTRAINT `fk_articles_users1`
    FOREIGN KEY (`create_user`)
    REFERENCES `testDb`.`users` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  ADD CONSTRAINT `fk_articles_users2`
    FOREIGN KEY (`last_modifie_user`)
    REFERENCES `testDb`.`users` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION;

我收到以下错误,但我不明白为什么我应该为此建立一个索引。

错误代码:1822。添加外键约束失败。引用表“users”中的约束“fk_articles_users1”缺少索引

我主动了

SHOW ENGINE innodb STATUS;

但这并没有显示任何错误。

【问题讨论】:

  • 如果将id 声明为主键,则不需要单独的唯一索引。我的猜测是两者都会混淆 MySQL。
  • 我试过没有UNIQUE,还是一样的问题。
  • 。 .您声称有两个表,但代码引用了三个。没有recipes - 很难确定问题出在哪里。
  • 对不起,你是对的。我将一些代码混合在一起。我编辑它。
  • 谁否决了这个问题? =( 仍然没有解决,它似乎不是像不同数据类型这样的常见错误之一

标签: mysql sql foreign-keys


【解决方案1】:

alter table 语句中一定有一些微妙的问题。更改articles 的定义可以解决问题:

CREATE TABLE IF NOT EXISTS `articles` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NULL,
  `description` VARCHAR(255) NULL,
  `create_user` INT ZEROFILL NOT NULL REFERENCES users(id),
  `create_date_time` DATETIME NULL,
  `last_modifie_user` INT ZEROFILL NOT NULL REFERENCES users(id),
  `last_modifie_date_time` DATETIME NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_articles_users1_idx` (`create_user` ASC),
  INDEX `fk_articles_users2_idx` (`last_modifie_user` ASC)
)
ENGINE = InnoDB
AUTO_INCREMENT = 1;

Here 是 SQL Fiddle。

【讨论】:

    【解决方案2】:

    create_user INT UNSIGNED ZEROFILL 不能引用 id INT,因为它们在外键引用时算作不同的数据类型。使它们具有相同的数据类型。

    外键关系中的列之间唯一允许的数据类型差异是 varchar 的长度。例如,VARCHAR(10) 可以引用 VARCHAR(20),反之亦然。

    数据类型、大小或字符集的任何其他差异都与参照完整性不兼容。

    即使在一个列上有ZEROFILL 而在另一列上没有,也会导致数据类型不兼容。

    【讨论】:

    • 谢谢比尔,我没有想到 ZEROFILL 会“更改”数据类型。我希望它类似于创建触发器。现在它的工作!
    • 对我来说,这是 UNSIGNED 属性。在 Sequal Pro 中,此字段如下所示 bit.ly/21uNJmT
    【解决方案3】:

    我遇到了这个问题,我的数据类型是正确的,所以我有点难过,但后来我把一切都做了一样。

    创建外键时,请确保您使用的列相同:

    • 数据类型
    • 整理
    • 零填充
    • 不为空
    • 未签名
    • 二进制

    【讨论】:

      【解决方案4】:

      您可以使用SHOW FULL COLUMNS FROM table_name,它返回一个列Collat​​ion,例如对于在列name 上具有特殊排序规则的表accounts

      mysql> SHOW FULL COLUMNS FROM accounts;
      +----------+--------------+-------------------+------+-----+---------+----------+
      | Field    | Type         | Collation         | Null | Key | Default | Extra    |
      +----------+--------------+-------------------+------+-----+---------+----------|
      | id       | int(11)      | NULL              | NO   | PRI | NULL    | auto_inc |
      | name     | varchar(255) | utf8_bin          | YES  |     | NULL    |          |
      | email    | varchar(255) | latin1_swedish_ci | YES  |     | NULL    |          |
      ...
      

      两列必须具有相同的排序规则。

      change the collation of column

      ALTER TABLE t1 MODIFY
          col1 VARCHAR(5)
            CHARACTER SET latin1
            COLLATE latin1_swedish_ci;
      

      这件事发生在我身上。

      【讨论】:

        【解决方案5】:

        就我而言,错误在于我不知道 FK 的名称在整个数据库中必须是唯一的。重命名 FK 解决了这个问题。

        【讨论】:

        • 在我的例子中,我从另一个数据库中导入了模型,一些表使用 Collat​​ion utf8_general_ci 和其他 latim_swedish_cli。
        【解决方案6】:

        对我来说,问题是我的数据库中的默认排序规则不同。确保您的数据库的默认排序规则与您的 FK 尝试引用的字段的排序规则相匹配。

        【讨论】:

          【解决方案7】:

          确保父表不是另一个表的子表。

          【讨论】:

          • 请在您的答案中添加一些解释,以便其他人可以从中学习
          【解决方案8】:

          由于某种原因,->unsignedBigInteger() 对我不起作用。

          所以我从这里稍微改变了一下: $table->unsignedBigInteger('owner_id');

          对此: $table->bigInteger('owner_id')->unsigned();

          现在它可以工作了!

          【讨论】:

            【解决方案9】:

            当您使用外键将一个表的一列引用到另一个表时 确保您所引用的列应该是主键或者应该是唯一的。 然后使用

            ALTER TABLE table_name1
            ADD CONSTRAINT constraint_name
            FOREIGN KEY(column_name_in_table_name1) 
            REFERENCES table_name2(column_name_in_table_name2);
            

            这对你有用。

            【讨论】:

              【解决方案10】:

              我在正向工程师期间在 mysql 工作台中收到此错误。在仔细检查索引和 fk 是否正确(唯一或​​ PK vals)后,我能够通过选择“跳过创建外键”和“跳过创建 FK 索引”来解决这个问题。

              然后我得到了一名成功的正向工程师,并选择了上述选项。在成功进行正向工程师之后,尝试在取消选择这些选项(默认)的情况下再次运行它。

              这对我有用。

              【讨论】:

                猜你喜欢
                • 2019-02-27
                • 2017-09-16
                • 2016-05-23
                • 2019-06-06
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多