mysql 5.6外键约束错误; 没有发生在5.5

Chr*_*nch 4 mysql foreign-keys

涉及的表格:

phppos_permissions_actions:

mysql> show create table phppos_permissions_actions;
+----------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table                      | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
+----------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_permissions_actions | CREATE TABLE `phppos_permissions_actions` (
  `module_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `person_id` int(11) NOT NULL,
  `action_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`module_id`,`person_id`,`action_id`),
  KEY `phppos_permissions_actions_ibfk_2` (`person_id`),
  KEY `phppos_permissions_actions_ibfk_3` (`action_id`),
  CONSTRAINT `phppos_permissions_actions_ibfk_1` FOREIGN KEY (`module_id`) REFERENCES `phppos_modules` (`module_id`),
  CONSTRAINT `phppos_permissions_actions_ibfk_2` FOREIGN KEY (`person_id`) REFERENCES `phppos_employees` (`person_id`),
  CONSTRAINT `phppos_permissions_actions_ibfk_3` FOREIGN KEY (`action_id`) REFERENCES `phppos_modules_actions` (`action_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+----------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

phppos_modules

mysql> show create table phppos_modules;
+----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table          | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                       |
+----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_modules | CREATE TABLE `phppos_modules` (
  `name_lang_key` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `desc_lang_key` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `sort` int(10) NOT NULL,
  `module_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`module_id`),
  UNIQUE KEY `desc_lang_key` (`desc_lang_key`),
  UNIQUE KEY `name_lang_key` (`name_lang_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

查询:

ALTER TABLE `phppos_permissions_actions` CHANGE `module_id` `module_id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, CHANGE `action_id` `action_id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
Run Code Online (Sandbox Code Playgroud)

错误:

#1832 - Cannot change column 'module_id': used in a foreign key constraint 'phppos_permissions_actions_ibfk_1'
Run Code Online (Sandbox Code Playgroud)

(在mysql 5.5中没有错误)

我可以让它工作的唯一方法是:

SET foreign_key_checks = 0;
Run Code Online (Sandbox Code Playgroud)

5.6中有什么变化?这是一个错误吗?

Bil*_*win 7

这显然是MySQL 5.6的一个改进,虽然实现看起来有点过于严格.

http://dev.mysql.com/doc/refman/5.6/en/alter-table.html说:

从5.6.7开始,服务器禁止更改外键列,否则可能导致参照完整性丢失.解决方法是在更改列定义之前使用ALTER TABLE ... DROP FOREIGN KEY,然后使用ALTER TABLE ... ADD FOREIGN KEY.

发行说明说这与http://bugs.mysql.com/bug.php?id=46599有关

那没关系......

http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html说:

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


你的评论:

这并不是一个矛盾.您仍然可以使用不同的字符串长度在MySQL 5.6中创建外键.

create table foo ( p varchar(20) primary key );
create table bar ( f varchar(10), foreign key (f) references foo (p) );
Run Code Online (Sandbox Code Playgroud)

只要没有截断数据的可能性,您就可以修改列.

alter table bar modify column f varchar(20); /* increasing string length */
Query OK
Run Code Online (Sandbox Code Playgroud)

但是,如果列可能会丢失数据,则无法对其进行修改.

alter table bar modify column f varchar(5); /* decreasing string length */
ERROR 1832 (HY000): Cannot change column 'f': 
used in a foreign key constraint 'bar_ibfk_1'
Run Code Online (Sandbox Code Playgroud)

正如您所发现的那样,您可以使用foreign_check_checks=0或通过使用ALTER TABLE删除约束来禁用外键检查,然后在修改列后重新创建约束.

  • 这些是varchar字段,所以这两个语句似乎都是矛盾的.我绕过它的方法是做SET foreign_key_checks = 0; (3认同)