MySQL无法创建外键约束

时间:2014-02-03 11:22:37

标签: mysql indexing foreign-keys

我在创建mysql数据库中现有表的外键时遇到了一些问题。

我有表exp

+-------------+------------------+------+-----+---------+-------+
| Field       | Type             | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| EID         | varchar(45)      | NO   | PRI | NULL    |       |
| Comment     | text             | YES  |     | NULL    |       |
| Initials    | varchar(255)     | NO   |     | NULL    |       |
| ExpDate     | date             | NO   |     | NULL    |       |
| InsertDate  | date             | NO   |     | NULL    |       |
| inserted_by | int(11) unsigned | YES  | MUL | NULL    |       |
+-------------+------------------+------+-----+---------+-------+

我不想创建一个名为sample_df的新表,引用它,使用以下内容:

CREATE TABLE sample_df (
df_id mediumint(5) unsigned AUTO_INCREMENT primary key,
sample_type mediumint(5) unsigned NOT NULL,
df_10 BOOLEAN NOT NULL,
df_100 BOOLEAN NOT NULL,
df_1000 BOOLEAN NOT NULL,
df_above_1000 BOOLEAN NOT NULL,
target INT(11) unsigned NOT NULL,
assay MEDIUMINT(5) unsigned zerofill NOT NULL,
insert_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
inserted_by INT(11) unsigned NOT NULL,
initials varchar(255),
experiment VARCHAR(45),
CONSTRAINT FOREIGN KEY (inserted_by) REFERENCES user (iduser),
CONSTRAINT FOREIGN KEY (target) REFERENCES protein (PID),
CONSTRAINT FOREIGN KEY (sample_type) REFERENCES sample_type (ID),
CONSTRAINT FOREIGN KEY (assay) REFERENCES assays (AID),
CONSTRAINT FOREIGN KEY (experiment) REFERENCES exp (EID)
);

但我收到错误:

ERROR 1215 (HY000): Cannot add foreign key constraint

要获得更多信息:

SHOW ENGINE INNODB STATUS\G

我从中得到:

FOREIGN KEY (experiment) REFERENCES exp (EID)
):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.

对我来说,列类型似乎匹配,因为它们都是varchar(45)。(我也尝试将experiment列设置为not null,但这并没有解决它)所以我猜问题必须是Cannot find an index in the referenced table where the referenced columns appear as the first columns。但我不太清楚这意味着什么,或者如何检查/修复它。有没有人有什么建议? first columns是什么意思?

解决方案:

我发现了我的问题。我对exp表(utf8_unicode_ci)有一个不同的排序规则,然后是数据库的默认排序(utf8_general_ci)。所以添加

CHARACTER SET utf8 COLLATE utf8_unicode_ci

在表创建查询结束时解决了我的问题。

但我仍然对first columns的含义感到好奇。它与索引有关吗?

15 个答案:

答案 0 :(得分:84)

只是把它放到可能原因的混合中,当参考表列具有相同的“类型”但没有相同的签名时,我遇到了这个。

在我的例子中,引用的表colum是TINYINT UNSIGNED,我的引用表列是TINYINT SIGNED。对齐两个列解决了这个问题。

答案 1 :(得分:18)

根据http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html

  

MySQL要求外键和引用键上的索引   外键检查可以很快,不需要表扫描。在里面   引用表时,必须有一个索引所在的外键   列以相同的顺序列为第一列。

     

InnoDB允许外键引用任何索引列或组   列。但是,在引用的表中,必须有一个索引   其中引用的列被列为的第一列   同样的顺序。

因此,如果引用表中的索引存在并且它由多个列组成,并且所需的列不是第一个,则应该发生错误。

我们错误的原因是由于违反了以下规则:

  

外键和引用键中的对应列必须   有类似的数据类型。整数类型的大小和符号必须是   相同。字符串类型的长度不必相同。对于   非二进制(字符)字符串列,字符集和排序规则   必须是一样的。

答案 2 :(得分:9)

如前所述@Anton,这可能是因为数据类型不同。 在我的情况下,我有主键BIGINT(20)并尝试使用INT(10)

设置foreight键

答案 3 :(得分:7)

如果引用表和当前表没有相同的字符集,也会发生此错误。

答案 4 :(得分:5)

@ austen-hoogen提出的解决方案解决了我的问题。但由于声誉得分低,我无法投票和评论他的解决方案。 在我的情况下,主键是整数,自动增量和无符号。但是外键(引用表的列)是签名类型。我将其更改为unsigned并能够成功创建关系。

答案 5 :(得分:3)

就我而言,事实证明引用的列未被声明为主要或唯一。

https://stackoverflow.com/a/18435114/1763217

答案 6 :(得分:2)

我的是引用表与要创建的表之间的排序规则问题,因此我必须显式设置我正在引用的键的排序规则类型。

  • 首先,我在被引用的表上运行查询以获取其归类类型
show table STATUS like '<table_name_here>';
  • 然后,我复制了排序规则类型,并在创建查询中明确声明了employee_id的排序规则类型。就我而言,它是 utf8_general_ci
CREATE TABLE dbo.sample_db
(
  id INT PRIMARY KEY AUTO_INCREMENT,
  event_id INT SIGNED NOT NULL,
  employee_id varchar(45) COLLATE utf8_general_ci NOT NULL,
  event_date_time DATETIME,
  CONSTRAINT sample_db_event_event_id_fk FOREIGN KEY (event_id) REFERENCES event (event_id),
  CONSTRAINT sample_db_employee_employee_id_fk FOREIGN KEY (employee_id) REFERENCES employee (employee_id)
);

答案 7 :(得分:2)

在我的情况下,

是使用 integer 作为ID创建的,并且引用表默认情况下是使用 bigint 创建外键的。

由于迁移失败,但是这实际上是在数据库中创建的,所以这在我的Rails应用程序中造成了巨大的噩梦,因此它们显示在数据库中,而不是在Rails应用程序的架构中显示。

答案 8 :(得分:1)

主键的精确顺序也需要匹配,中间没有多余的列。

我有一个主键设置实际上与列 order 匹配,但是问题是主键中有一个额外的列,该列不是引用表的外键的一部分

例如表2(a,b,c)列->表1(a,b,d,c)列-此失败

我不得不对主键列进行重新排序,以便不仅以相同的方式对其进行排序,而且中间没有多余的列:

例如表2(a,b,c)列->表1(a,b,c,d)列-此成功

答案 9 :(得分:1)

对我来说,这只是数据库的字符集和排序规则。我改成了utf8_unicode_ci,可以正常工作

答案 10 :(得分:0)

在同一个约束中多次引用同一列也会产生此Cannot find an index in the referenced table错误,但很难在大型表上发现。拆分约束,它将按预期工作。

答案 11 :(得分:0)

我也有这个错误。没有一个答案与我有关。就我而言,我的GUI自动创建一个表,该表的主要唯一标识符为“ unssigned”。当我尝试创建外键并给我完全相同的错误时,此操作将失败。我的主键需要分配。

如果您像这样col-xs编写SQL本身,那么就不会出现此问题,但是由于某种原因,我的GUI却id int unique auto_increment会这样做。

希望这可以帮助其他人。

答案 12 :(得分:0)

在某些情况下,除了将其定义为主键之外,我还必须使引用的字段唯一。

但是我发现不将其定义为唯一并不会在每种情况下造成问题。我还无法弄清楚情况。可能与可为空的定义有关。

答案 13 :(得分:0)

补充一点,我今天遇到了同样的问题

两个字段的长度都是 int,等等,但是,一个是 unsigned,这足以打破它。

两者都需要声明为 unsigned

答案 14 :(得分:0)

就我而言,它与 ENGINE 和 COLLATE 不兼容,一旦我添加了 ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci,它就起作用了

CREATE TABLE `some_table` (
      `id` varchar(36) NOT NULL,
      `col_id` varchar(36) NOT NULL,
      
      PRIMARY KEY (`id`),
      CONSTRAINT `FK_some_table_cols_col_id` FOREIGN KEY (`col_id`) REFERENCES `ref_table` (`id`) ON DELETE CASCADE,
      
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;