我有一个非常奇怪(又可怕)的问题:我的mySQL数据库通常忽略外键约束!
我的所有表格都是InnoDB
,我正在用liquibase创建它们:
<addForeignKeyConstraint baseColumnNames="user_account_id"
baseTableName="account_transaction"
constraintName="fk_account_transaction_user_account_id"
referencedColumnNames="id"
referencedTableName="user_account"/>
我还检查了FOREIGN_KEY_CHECKS
并将其设置为1(SET FOREIGN_KEY_CHECKS=1;
)
我的所有ID列的数据类型都为BIGINT
(如果重要的话,请注意dunno)。
还值得一提:以下声明
SELECT * FROM information_schema.TABLE_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = DATABASE();
返回一堆约束,但没有外键约束......当我在本地mySQL DB上执行相同的语句时,它返回所有约束INCLUDING外键约束。我无法弄清楚它们之间的区别但是......
非常感谢任何帮助:)
@Update: 所以MyISAM和InnoDB的暗示就是诀窍。我之前做过调查。但是,出于某种原因,我的表是InnoDB,但我的数据库是MyISAM。我将对此进行进一步调查:)
答案 0 :(得分:1)
Bill Karwin在评论中指出,如果表格不是InnoDB,则FOREIGN KEY约束忽略。
演示:
CREATE TABLE foo_p
( id BIGINT UNSIGNED PRIMARY KEY
) ENGINE=MYISAM
;
CREATE TABLE foo_c
( id BIGINT UNSIGNED PRIMARY KEY
, p_id BIGINT UNSIGNED
) ENGINE=MYISAM
;
添加外键约束:
ALTER TABLE foo_c
ADD CONSTRAINT fk_foo_c_foo_p
FOREIGN KEY (id) REFERENCES foo_p (id)
ON DELETE NO ACTION ON UPDATE NO ACTION
;
MySQL创建索引但不创建外键。
将存储引擎更改为InnoDB不会创建外键:
ALTER TABLE foo_p ENGINE=INNODB ;
ALTER TABLE foo_c ENGINE=INNODB ;
使用SHOW CREATE TABLE foo_c
查看表格定义:
CREATE TABLE `foo_c` (
`id` BIGINT(20) UNSIGNED NOT NULL,
`p_id` BIGINT(20) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_foo_c_foo_p` (`id`)
) ENGINE=INNODB
有一个索引(从MyISAM定义转换而来)但没有外键。
添加外键:
ALTER TABLE foo_c
DROP KEY fk_foo_c_foo_p
, ADD CONSTRAINT fk_foo_c_foo_p
FOREIGN KEY (p_id) REFERENCES foo_p (id)
ON DELETE NO ACTION ON UPDATE NO ACTION
;
SHOW CREATE TABLE
显示FOREIGN KEY约束,以及自动创建的索引:
CREATE TABLE `foo_c` (
`id` BIGINT(20) UNSIGNED NOT NULL,
`p_id` BIGINT(20) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_foo_c_foo_p` (`p_id`),
CONSTRAINT `fk_foo_c_foo_p` FOREIGN KEY (`p_id`) REFERENCES `foo_p` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=INNODB