MySQL DB正在忽略外键约束

rsl1atfo  于 2023-01-25  发布在  Mysql
关注(0)|答案(2)|浏览(96)

我有一个非常奇怪(和可怕)的问题:我的mySQL DB通常忽略外键约束!
我所有的表都是InnoDB,我使用liquibase创建它们,如下所示:

<addForeignKeyConstraint baseColumnNames="user_account_id"
    baseTableName="account_transaction"
    constraintName="fk_account_transaction_user_account_id"
    referencedColumnNames="id"
    referencedTableName="user_account"/>

外键创建得很好,在HeidiSQL中我看到它们是这样的:

我还检查了FOREIGN_KEY_CHECKS,并将其设置为1(SET FOREIGN_KEY_CHECKS=1;
我的所有ID列都具有数据类型BIGINT(不知道这是否重要)。
还值得一提的是:以下语句

SELECT * FROM information_schema.TABLE_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = DATABASE();

返回一堆约束,但没有外键约束...当我在本地mySQL DB上执行相同的语句时,它返回所有约束,包括外键约束。但我不知道它们之间有什么区别...
任何帮助都非常感谢:)
@更新:MyISAM和InnoDB的提示起到了作用。我之前确实研究过这个问题。但是,由于某种原因,我的表是InnoDB,而我的数据库是MyISAM。我将进一步研究这个问题:)

arknldoa

arknldoa1#

正如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创建了一个 * index *,但没有创建外键。
将存储引擎更改为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
k10s72fa

k10s72fa2#

我的问题是,我信任MySQL文档。根据它外键可以定义为列定义的一部分,这在我的情况下是不正确的。下面是一个例子:

CREATE TABLE parent (id INT PRIMARY KEY);
CREATE TABLE badchild (id INT PRIMARY KEY, parent_id INT REFERENCES parent(id));
CREATE TABLE goodchild (id INT PRIMARY KEY, parent_id INT, FOREIGN KEY(parent_id) REFERENCES parent(id));

goodchild有外键,badchild没有外键。语句没有失败,只是静默忽略指令。它是在Windows上运行的MySQL 8.0.20,可能在一些更高版本中得到了修复。

相关问题