【问题标题】:MySQL : ERROR 1215 (HY000): Cannot add foreign key constraintMySQL : ERROR 1215 (HY000): 无法添加外键约束
【发布时间】:2013-09-26 15:03:56
【问题描述】:

我已阅读 数据库系统概念,第 6 版,Silberschatz。我将在 MySQL 上的 OS X 上实现第 2 章中所示的大学数据库系统。但是我在创建表course 时遇到了麻烦。表department 看起来像

mysql> select * from department
    -> ;
+------------+----------+-----------+
| dept_name  | building | budget    |
+------------+----------+-----------+
| Biology    | Watson   |  90000.00 |
| Comp. Sci. | Taylor   | 100000.00 |
| Elec. Eng. | Taylor   |  85000.00 |
| Finance    | Painter  | 120000.00 |
| History    | Painter  |  50000.00 |
| Music      | Packard  |  80000.00 |
| Physics    | Watson   |  70000.00 |
+------------+----------+-----------+

mysql> show columns from department
    -> ;
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| dept_name | varchar(20)   | NO   | PRI |         |       |
| building  | varchar(15)   | YES  |     | NULL    |       |
| budget    | decimal(12,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+

创建表course会导致以下错误。

mysql> create table course
    -> (course_id varchar(7),
    -> title varchar (50),
    -> dept_name varchar(20),
    -> credits numeric(2,0),
    -> primary key(course_id),
    -> foreign key (dept_name) references department);
ERROR 1215 (HY000): Cannot add foreign key constraint

在google上搜索外键约束后,我才知道“外键约束”这个词表示表course中的外键列的数据必须存在于表department的主键列中。但是我应该在插入数据时遇到这个错误。

如果不是,为什么作者让我执行那个 SQL 语句?

如果我真的执行了错误的SQL语句,插入一些数据后是否必须在课程表中指定dept_name作为外键?

编辑:在mysql> 中输入set foreign_key_checks=0 并不能修复错误。

------------------------
LATEST FOREIGN KEY ERROR
------------------------
2013-09-21 16:02:20 132cbe000 Error in foreign key constraint of table university/course:
foreign key (dept_name) references department):
Syntax error close to:
)
mysql> set foreign_key_checks=0
    -> ;
Query OK, 0 rows affected (0.00 sec)
mysql> create table course
    -> (course_id varchar(7),
    -> title varchar(50),
    -> dept_name varchar(20),
    -> credits numeric(2,0),
    -> primary key(course_id),
    -> foreign key (dept_name) references department);
ERROR 1215 (HY000): Cannot add foreign key constraint

【问题讨论】:

  • 两个表中的所有 dept_name 都是 varchar(15)。我必须在哪里输入set foreign_key_checks=0
  • LATEST FOREIGN KEY ERROR 说什么?
  • foreign key (dept_name) references department 是 ANSI 标准 SQL。也许作者没有使用 MySQL,而是使用了更符合标准的 DBMS。
  • @inherithandle:作者确实给了你正确的SQL,只是MySQL在这方面(以及许多其他)不符合ANSI标准

标签: mysql sql database


【解决方案1】:

当你得到这个模糊的错误信息时,你可以通过运行找出更具体的错误

SHOW ENGINE INNODB STATUS;

最常见的原因是创建外键时,被引用的字段和外键字段都需要匹配:

  • Engine 应该是相同的 e.g. InnoDB
  • 数据类型应该相同,并且长度相同。
    例如VARCHAR(20) 或 INT(10) 无符号
  • 排序规则应该相同。 例如utf8
  • 唯一 - 外键应该引用引用表中唯一的字段(通常是私有的)

此错误的另一个原因是:
尽管某些列被定义为 NOT NULL,但您已经定义了 SET NULL 条件。

【讨论】:

  • 我刚刚被绊倒了,因为一个字段是 UNSIGNED 而另一个不是,所以只需编辑您的答案以包含该字段。希望没关系。
  • @SimonEast 为我指出正确的方向有同样的问题:)
  • 这应该是已接受的答案,因为它对找到此页面并寻找问题解决方案的人最有帮助
  • 遇到了同样的问题:如果使用ON DELETE SET NULL,所有列都必须看起来可以为空。 Here is another question.
  • 我收到了这个错误,因为引用的表没有用ENGINE=InnoDB 标记 - 这在 very badly 格式的输出中也不明显SHOW ENGINE INNODB STATUS;
【解决方案2】:

FOREIGN KEY 对应 CREATE TABLE 的语法结构如下:

FOREIGN KEY (index_col_name)
        REFERENCES table_name (index_col_name,...)

所以你的 MySQL DDL 应该是:

 create table course (
        course_id varchar(7),
        title varchar(50),
        dept_name varchar(20),
        credits numeric(2 , 0 ),
        primary key (course_id),
        FOREIGN KEY (dept_name)
            REFERENCES department (dept_name)
    );

另外,在department 表中dept_name 应该是VARCHAR(20)

更多信息可以在MySQL documentation找到

【讨论】:

  • 我很乐意为您详细解释该语句是什么。我从未见过CONSTRAINT 的声明。
  • CONSTRAINT link_dept_course 给这种关系一个符号。它是可选的。如果没有给出子句,或者 CONSTRAINT 关键字后面没有包含符号,则会自动创建约束名称。仅供参考:dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
  • 约束部分是可选的,但是PK列的列表不是。所以references departmentreferences department (dept_name) 确实修复了它。我不知道 MySQL 不支持“速记”表示法(由 SQL 标准定义)
  • 我还发现如果你的表有多个主键列,外键约束将无法添加。
【解决方案3】:

也许您的dept_name 列有不同的字符集。

您可以尝试更改其中一个或两个:

ALTER TABLE department MODIFY dept_name VARCHAR(20) CHARACTER SET utf8;
ALTER TABLE course MODIFY dept_name VARCHAR(20) CHARACTER SET utf8;

【讨论】:

  • 那个很棘手。我有一个表使用明确的 UTF8,而不是另一个。迁移到不使用 UTF8 作为默认值的服务器时,工作模式停止工作。这救了我!
  • 感谢您的回答,在我的情况下,主键是 utf8_bin,而“wannabe-foreign”是 utf8_general_ci。这也救了我!
【解决方案4】:
foreign key (dept_name) references department

此语法对 MySQL 无效。它应该是:

foreign key (dept_name) references department(dept_name)

MySQL requires dept_name to be used twice。一次定义外部列,一次定义主列。

13.1.17.2。使用外键约束

...CREATE TABLEALTER TABLE 语句中外键约束定义的基本语法如下所示:

[CONSTRAINT [symbol]] FOREIGN KEY
    [index_name] (index_col_name, ...)
    REFERENCES tbl_name (index_col_name, ...)
    [ON DELETE reference_option]
    [ON UPDATE reference_option]

reference_option:
    RESTRICT | CASCADE | SET NULL | NO ACTION

【讨论】:

    【解决方案5】:

    如果外键不是自己表中的主键,也可能出现此错误。

    我做了一个 ALTER TABLE 并且不小心删除了一个列的主键状态,并得到了这个错误。

    【讨论】:

      【解决方案6】:

      ERROR 1215 (HY000): 无法添加外键约束

      还值得注意的是,当另一个able 中作为外键的列的type 与正确表中的列不显式匹配时,您会收到此错误。

      例如:

      alter table schoolPersons
               add index FKEF5AB5E532C8FBFA (student_id),
               add constraint FKEF5AB5E532C8FBFA
               foreign key (student_id)
               references student (id);
      ERROR 1215 (HY000): Cannot add foreign key constraint
      

      这是因为student_id 字段被定义为:

      mysql> desc schoolPersons;
      +--------------------+------------+------+-----+---------+----------------+
      | Field              | Type       | Null | Key | Default | Extra          |
      +--------------------+------------+------+-----+---------+----------------+
      | student_id         | bigint(20) | YES  |     | NULL    |                |
      

      student 表中的id 字段定义为:

      mysql> desc persons;
      +--------------+----------------------+------+-----+-------------------+-----------------+
      | Field        | Type                 | Null | Key | Default           | Extra           |
      +--------------+----------------------+------+-----+-------------------+-----------------+
      | id           | int(10) unsigned     | NO   | PRI | NULL              | auto_increment  |
      

      bigint(20)(由 java long 通过 hibernate 生成)与 int(10) unsigned(Java int)不兼容。

      【讨论】:

        【解决方案7】:

        只需为 FOREIGN 约束添加“无符号”

        `FK` int(11) unsigned DEFAULT NULL,
        

        【讨论】:

          【解决方案8】:

          我不像你那样遇到问题。但我收到相同的错误消息。所以我把它标记在这里以方便其他人。

          如果列类型为charvarchar,请检查两个表的字符集。我使用charset=gbk,但我创建了一个默认为charset=utf8 的新表。所以字符集不一样。

          ERROR 1215 (HY000): Cannot add foreign key constraint
          

          要解决它是使用相同的字符集。例如utf8

          【讨论】:

            【解决方案9】:

            值得注意的是,如果您在 REFERENCES 部分中使用的目标表或列根本不存在,也会发生此错误。

            【讨论】:

              【解决方案10】:

              以下代码对我有用

              set @@foreign_key_checks=0;
              ALTER TABLE  `table1` ADD CONSTRAINT `table1_fk1` FOREIGN KEY (`coloumn`) REFERENCES `table2` (`id`) ON DELETE CASCADE;
              

              【讨论】:

                【解决方案11】:

                在我的情况下,父表和子表之间的引擎是不同的。使引擎相等是有效的

                问题: 父表 'engine' => 'MyISAM', 子表 'engine' => 'innoDB',

                更正: 父表 'engine' => 'MyISAM', 子表 'engine' => 'MyISAM',

                【讨论】:

                • 这并不能真正回答问题。如果您有其他问题,可以点击 进行提问。要在此问题有新答案时收到通知,您可以follow this question。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。 - From Review
                【解决方案12】:

                我没有看到任何人明确说明这一点,并且我收到了同样的错误消息,我的问题是我试图将外键添加到 TEMPORARY 表中。不允许使用noted in the manual

                外键关系涉及一个包含中心数据值的父表,以及一个具有相同值的子表指向其父表。 FOREIGN KEY 子句在子表中指定。父表和子表必须使用相同的存储引擎。 它们不能是 TEMPORARY 表。

                (强调我的)

                【讨论】:

                  【解决方案13】:

                  我也遇到了同样的问题。不知道为什么这是有效的,但它确实有效: 尝试在创建查询后添加 ENGINE INNODB。

                  mysql> create table course
                  -> (course_id varchar(7),
                  -> title varchar (50),
                  -> dept_name varchar(20),
                  -> credits numeric(2,0),
                  -> primary key(course_id),
                  -> foreign key (dept_name) references department) ENGINE INNODB;
                  

                  【讨论】:

                    【解决方案14】:

                    即使这与您的情况没有直接联系,它也可能有助于进一步的读者注意,如果您不遵守创建数据库表的顺序,您在键入show engine innodb mstatus 时会得到完全相同的错误输出;这意味着您不能添加引用尚不存在的表的外部约束。引用表必须在指向它的表之前存在。

                    当遵守表创建顺序但不遵守外键约束中涉及的列时也是如此。

                    【讨论】:

                      【解决方案15】:

                      在我的例子中,charset 中的数据类型都是正确的。经过调查,我发现在父表中,外键列上没有索引。一旦添加的问题得到解决。

                      【讨论】:

                        【解决方案16】:

                        当我尝试从 PhpAdminMySQL 导出中导入(在 MysqlWorkbench 中)时,我遇到了这个错误。验证后我已禁用唯一键和外键:

                        SET unique_checks=0;
                        SET foreign_key_checks = 0;
                        

                        我仍然遇到同样的错误(MySQL : ERROR 1215 (HY000): Cannot add foreign key constraint)。此创建语句发生错误。

                        DROP TABLE IF EXISTS `f1_pool`;
                        CREATE TABLE `f1_pool` (
                         `id` int(11) NOT NULL,
                         `name` varchar(45) NOT NULL,
                         `description` varchar(45) DEFAULT NULL COMMENT 'Optional',
                         `ownerId` int(11) NOT NULL,
                         `lastmodified` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
                        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
                        

                        没有外键或唯一索引,那么这里出了什么问题? 最后(令人费解的 90 分钟后)我决定重新启动 MySQL 并通过一项修改再次进行导入:我在导入之前删除了所有表。 并且没有错误,所有功能正常,表和视图恢复。 所以我的建议,如果一切正常,首先尝试重启 MySQL!

                        【讨论】:

                          【解决方案17】:

                          请注意,它可以是几种不同的东西。

                          在我的情况下,它是表/字段排序规则:

                          • FK 目标:CHARSET=utf8 COLLATE=utf8_unicode_ci
                          • FK 源字段:CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

                          【讨论】:

                            【解决方案18】:
                            CONSTRAINT vendor_tbfk_1 FOREIGN KEY (V_CODE) REFERENCES vendor (V_CODE) ON UPDATE CASCADE
                            

                            可能是这样...查看引用列部分。 (V_code)

                            【讨论】:

                              猜你喜欢
                              • 2014-03-27
                              • 2018-09-09
                              • 1970-01-01
                              • 1970-01-01
                              • 2014-08-24
                              • 1970-01-01
                              • 2021-09-24
                              • 2017-09-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多