我正在使用DBIc模式包装数据库模式,以帮助对代码进行单元测试。
基于原始数据库,我使用dbidump
从数据库生成模式:
dbicdump -o dump_directory=./lib -o components='["InflateColumn::DateTime"]' -o debug=1 Test::Schema 'dbi:mysql:dbname=mcdowall_test' 'test'
有2个InnoDB表table_a
和table_b
。问题是table_a
在表table_b
上具有外键约束:
CREATE TABLE `table_b` (
`table_b_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`source_id` INT UNSIGNED NULL,
PRIMARY KEY (`table_b_id`),
KEY (`source_id`))
ENGINE = InnoDB;
CREATE TABLE `table_a` (
`table_a_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`source_id` INT UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`table_a_id`),
KEY (`table_a_id`),
CONSTRAINT `fk_ab`
FOREIGN KEY (`source_id`)
REFERENCES `table_b` (`source_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
这意味着在测试过程中使用deploy()
安装架构时,它将以字母顺序安装表:
use Test::Schema
my $schema = Test::Schema->connect($dsn, $user, $pass, \%opts);
$schema->deploy();
由于创建table_b
时table_a
不存在,因此会引发以下SQL错误:
ERROR 1215 (HY000): Cannot add foreign key constraint
是否可以通过获取deploy()
函数来预先检查外键依赖关系或指定要首先插入的特定表?
理想情况下,应先安装table_b
,然后再安装table_a
。
答案 0 :(得分:0)
事实证明,查询对订单敏感,因为在定义第二张表时缺少索引。在描述的示例中,table_a
的定义是相同的,但是table_b
的定义是:
CREATE TABLE `table_b` (
`table_b_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`source_id` INT UNSIGNED NULL,
PRIMARY KEY (`table_b_id`))
ENGINE = InnoDB;
以table_b
然后table_a
的顺序运行时,一切都很好。如果按照table_a
然后table_b
的顺序进行调用,因为source_id
的定义中table_b
上缺少索引,则查询是否会失败{ {1}}设置为0或1。
通过在DBIc中打开debug()设置以查找其运行的查询,然后在Percona博客上使用此post来减少问题并找到答案,从而找到了答案。
然后在表定义中,使用模式加载程序创建的样板代码下方的FOREIGN_KEY_CHECKS
添加索引:
sqlt_deploy_hook
感谢那些看过这个问题或花了一些时间来考虑这个问题的人。