MySQL不会让我在表中添加外键。没有错误消息

时间:2015-10-26 01:50:36

标签: mysql foreign-keys

我使用此查询:

ALTER TABLE recent_article_entry ADD FOREIGN KEY (`article`) REFERENCES article(`id`);

或者这个:

ALTER TABLE recent_article_entry ADD CONSTRAINT fk_rae_article FOREIGN KEY (article) REFERENCES article(id);

它说No errors; 1 row affected, taking 127 ms

哪一行受到了影响?

如果我转到information_schema.KEY_COLUMN_USAGE,我在那里看不到我新生成的外键。如果我尝试添加到recent_article_entry,则不会强制执行约束。

我很困惑。我试图通过将一些值更改为jibberish来调试查询。

所以:

ALTER TABLE sldakjfalksdjf ADD FOREIGN KEY (`article`) REFERENCES article(`id`); 

按预期失败,

ALTER TABLE recent_article_entry ADD FOREIGN KEY (`aslkdjfalksjdf`) REFERENCES article(`id`);

按预期失败。

但无论出于何种原因,

ALTER TABLE recent_article_entry ADD FOREIGN KEY (`article`) REFERENCES aslkdjfdkf(`id`); 

成功(以及将引用的列更改为jibberish)。我以前做过很多外键。为什么MySQL突然忽略了我的查询而没有创建外键?

编辑根据ray的请求,以下是describe语句的输出:

describe recent_article_entry

Field        |Type       |Null|Key|Default|Extra
-------------|-----------|----|---|-------|-----
article      |varchar(55)|NO  |PRI|       |
file_location|varchar(55)|NO  |PRI|       |

describe article

Field         |Type          |Null |Key|Default          |Extra
--------------|--------------|-----|---|-----------------|-----
id            |varchar(55)   |NO   |PRI|                 |
title         |varchar(255)  |YES  |   |NULL             |
author        |varchar(55)   |NO   |MUL|                 |
translator    |varchar(55)   |NO   |MUL|                 |
source        |varchar(1000) |YES  |MUL|0                |
published_flag|tinyint(1)    |NO   |   |                 |
published     |timestamp     |YES  |   |CURRENT_TIMESTAMP|
short_title   |varchar(55)   |YES  |   |NULL             |

describe file_location

Field |Type       |Null |Key|Default          |Extra
------|-----------|-----|---|-----------------|-----
id    |varchar(55)|NO   |PRI|                 |
views |int(11)    |YES  |   |NULL             |

版本为 5.1.56-log

1 个答案:

答案 0 :(得分:2)

可能的原因 - 整理和编码

在尝试在表之间创建FK约束时,我经常看到MySQL不够丰富。我多年前被烧毁的一个特定实例是相关列的表格排序和/或字符串编码。他们必须匹配两个表。换句话说,您应该验证,如果某个表VARCHAR中的A PK列使用latin1编码,那么某些表VARCHAR中的B FK列}必须使用latin1 enconding而不是其他内容,例如utf8

在下一节中,我将重现您的基本设置,但我确保表格排序和列编码是相同的。就我而言,它们是默认的,但您应该检查自己的数据库表以确定。

可能的原因 - 存储引擎

在旧版本的MySQL中(您使用的是5.1,我使用的是5.7),默认存储引擎是MyISAM。此存储引擎 ACID-compliant。因此,它不支持外键约束。您必须确保每个表的存储引擎都设置为 InnoDB

您可以在MySQL配置文件中将其指定为默认值,也可以将其指定为create table SQL语句的一部分。目前,这个似乎更有可能,因为您说您的查询不会产生错误消息。话虽如此,我不会立即回想起以前的可能性是否会产生消息或保持沉默。

在下一部分中,我展示了这种情况正常,至少对我而言,包括您提供的查询。

创建表

我试图为你的桌子重现一些基础知识,足以在他们之间设置PK和FK。它们将在下面转载,包括create声明:

mysql> create table `test`.`article` (
    `id` varchar(55) not null,
    `title` varchar(255) null default null,
    primary key (`id`)
);
Query OK, 0 rows affected (0.42 sec)

mysql> create table `test`.`file_location` (
    `id` varchar(55) not null,
    `views` int(11) null default null,
    primary key (`id`)
);
Query OK, 0 rows affected (0.35 sec)

mysql> create table `test`.`recent_article_entry` (
    `article` varchar(55) not null,
    `file_location` varchar(55) not null,
    primary key (`article`, `file_location`)
);
Query OK, 0 rows affected (0.32 sec)

表格如下describe d:

mysql> show tables;
+----------------------+
| Tables_in_test       |
+----------------------+
| article              |
| file_location        |
| recent_article_entry |
+----------------------+
3 rows in set (0.00 sec)

mysql> describe article;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | varchar(55)  | NO   | PRI | NULL    |       |
| title | varchar(255) | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> describe file_location;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | varchar(55) | NO   | PRI | NULL    |       |
| views | int(11)     | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> describe recent_article_entry;
+---------------+-------------+------+-----+---------+-------+
| Field         | Type        | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+-------+
| article       | varchar(55) | NO   | PRI | NULL    |       |
| file_location | varchar(55) | NO   | PRI | NULL    |       |
+---------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

创建约束

我们在这里检查添加外键之前的列使用情况,并注意它们不会显示,因为它们还不存在:

mysql> select TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.KEY_COLUMN_USAGE;
+----------------------+---------------+-------------------------+-----------------------+------------------------+
| TABLE_NAME           | COLUMN_NAME   | REFERENCED_TABLE_SCHEMA | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+----------------------+---------------+-------------------------+-----------------------+------------------------+
| article              | id            | NULL                    | NULL                  | NULL                   |
| file_location        | id            | NULL                    | NULL                  | NULL                   |
| recent_article_entry | article       | NULL                    | NULL                  | NULL                   |
| recent_article_entry | file_location | NULL                    | NULL                  | NULL                   |
+----------------------+---------------+-------------------------+-----------------------+------------------------+
4 rows in set (0.00 sec)

我继续在我的测试数据库中使用以下查询创建了FK:

alter table `test`.`recent_article_entry`
    add constraint `fk_recent_article_entry_article_id`
        foreign key (`article`)
        references `test`.`article` (`id`)
        on delete restrict
        on update cascade,

    add constraint `fk_recent_article_entry_file_location`
        foreign key (`file_location`)
        references `test`.`file_location` (`id`)
        on delete restrict
        on update cascade;

然后我像以前一样检查了information_schema。您现在可以看到列出的约束:

mysql> select TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.KEY_COLUMN_USAGE;
+----------------------+---------------+-------------------------+-----------------------+------------------------+
| TABLE_NAME           | COLUMN_NAME   | REFERENCED_TABLE_SCHEMA | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+----------------------+---------------+-------------------------+-----------------------+------------------------+
| article              | id            | NULL                    | NULL                  | NULL                   |
| file_location        | id            | NULL                    | NULL                  | NULL                   |
| recent_article_entry | article       | NULL                    | NULL                  | NULL                   |
| recent_article_entry | file_location | NULL                    | NULL                  | NULL                   |
| recent_article_entry | article       | test                    | article               | id                     |
| recent_article_entry | file_location | test                    | file_location         | id                     |
+----------------------+---------------+-------------------------+-----------------------+------------------------+
6 rows in set (0.00 sec)

我知道我的查询与您的查询相比看起来有所不同,但是您的查询也适合我,我接下来会展示。我删除了上面显示的FK ,然后尝试自己的查询:

mysql> alter table recent_article_entry add foreign key (`article`) references article(`id`);
Query OK, 0 rows affected (0.56 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> select TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.KEY_COLUMN_USAGE;
+----------------------+---------------+-------------------------+-----------------------+------------------------+
| TABLE_NAME           | COLUMN_NAME   | REFERENCED_TABLE_SCHEMA | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+----------------------+---------------+-------------------------+-----------------------+------------------------+
| article              | id            | NULL                    | NULL                  | NULL                   |
| file_location        | id            | NULL                    | NULL                  | NULL                   |
| recent_article_entry | article       | NULL                    | NULL                  | NULL                   |
| recent_article_entry | file_location | NULL                    | NULL                  | NULL                   |
| recent_article_entry | article       | test                    | article               | id                     |
+----------------------+---------------+-------------------------+-----------------------+------------------------+

正如您所看到的,您自己的查询对我来说很好。如果您有其他问题或发现您认为我可能错过的内容,请在评论中告诉我。