mysql - InnoDB - 双向多对多外键检查
问题描述
我正在尝试在表中建立多对多关系: a keyword
can 与 another 相关keyword
,并且当添加该关系时,还必须建立另一个方向。
上运行10.5.9-MariaDB
。
CREATE TABLE `related_keywords` (
`relation_id` int(12) NOT NULL AUTO_INCREMENT COMMENT 'Laravel/Eloquent pk crutch',
`keyword_1` bigint(20) unsigned NOT NULL,
`keyword_2` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`relation_id`),
UNIQUE KEY `rel_kw_left_to_right` (`keyword_1`,`keyword_2`),
UNIQUE KEY `rel_kw_right_to_left` (`keyword_2`,`keyword_1`),
CONSTRAINT `fk_rel_kw_1_exists` FOREIGN KEY (`keyword_1`) REFERENCES `keywords` (`keyword_id`) ON DELETE CASCADE,
CONSTRAINT `fk_rel_kw_2_exists` FOREIGN KEY (`keyword_2`) REFERENCES `keywords` (`keyword_id`) ON DELETE CASCADE,
CONSTRAINT `fk_related_kw_lr` FOREIGN KEY (`keyword_1`, `keyword_2`) REFERENCES `related_keywords` (`keyword_2`, `keyword_1`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `ck_rel_kw_differ` CHECK (`keyword_1` <> `keyword_2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
为了添加一个,还必须添加另一个。同样,删除一行必须删除另一行。但是,由于外键检查强制执行此操作,我无法在不添加第二个的情况下添加第一个:
INSERT INTO related_keywords (keyword_1, keyword_2) VALUES
(119250770368532480, 119251038153871360),
(119251038153871360, 119250770368532480);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`keyword_db`.`related_keywords`, CONSTRAINT `fk_related_keyword_lr` FOREIGN KEY (`keyword_1`, `keyword_2`) REFERENCES `related_keywords` (`keyword_2`, `keyword_1`) ON DELETE CASCADE ON UPDATE )
现在,我尝试在事务中运行它,但它似乎仍然检查外键(我觉得很奇怪)。我实际上可以添加它的唯一方法是在插入期间禁用外键检查,我真的不喜欢。
这里的理想解决方案是这样,在应用程序级别,我所要做的就是:
INSERT INTO related_keywords (keyword_1, keyword_2) VALUES (119250770368532480, 119251038153871360);
并且匹配的行也会自动添加,fk_related_kw_lr
外键检查没有问题。
我通常在文档中搜索 MariaDB 和 InnoDB,即使使用 MariaDB 10.x 的新功能,我似乎也无法找到解决方法
- 暂时禁用单个(多个)约束
- 将约束检查推迟到事务结束
- ...并在插入第一个行时插入匹配的相反方向行
有任何想法吗?
解决方案
PK没用
只
UNIQUE
需要一个3 唯一性减慢插入速度。
最佳多对多:http: //mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
我怀疑你是否需要“级联”。
放弃 FK,它们可能带来的麻烦多于其价值。
考虑添加一行,而不是添加 2 行,如下所示。(这可能会有所帮助,也可能会使事情复杂化,具体取决于您对此表的用途。)
LEAST(1234, 2345), GREATEST(1234, 2345)
推荐阅读
- python - 如何在文本输入框内添加滚动条
- typescript - 通用方法的打字稿接口
- terraform - 如何针对单个 ECS 服务附加两个目标组
- jenkins - 在 GitHub 上重命名 jenkins
- node.js - Heroku - React 应用程序在 fetch() 请求中调用 localhost,而不是我的 Express 后端的 Heroku URL
- python - NaN 是否会干扰 pandas 中的列连接?
- php - 我的联系表格工作正常,直到我添加了附件选项。不再发送消息。知道如何验证附件字段吗?
- python-3.x - 有选择地更新数据框(python)的多级列名称,具有特定文本的列具有特定名称
- azure - Azure 自动化特权
- angularjs - 组件 templateUrl 不适用于规范