如何将自动递增的主键也用作外键?
Posted
技术标签:
【中文标题】如何将自动递增的主键也用作外键?【英文标题】:How to use an auto incremented primary key as a foreign key as well? 【发布时间】:2011-04-02 10:34:10 【问题描述】:这就是我想要做的:
我有 2 张桌子...
CREATE TABLE `parent` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `child` (
`parent_id` int(11) DEFAULT NULL,
`related_ids` int(11) DEFAULT NULL,
KEY `parent_id` (`parent_id`),
KEY `related_ids` (`related_ids`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
然后是一个约束:
ALTER TABLE `parent` ADD FOREIGN KEY (`id`) REFERENCES `child` (`parent_id`);
如您所见,父表有一个自动递增的主键“id”,它也被用作子表的外键。
现在我想在父表中插入一条记录,如下所示:
INSERT INTO parent SET DATA="abc";
它失败并出现错误:
无法添加或更新子行:a 外键约束失败 (
myschema
.parent
, 约束parent_ibfk_1
外键 (id
) 参考child
(parent_id
))
我知道它失败是因为它在子表中找不到引用的记录。如果我首先在子表中创建一条记录,将其 parent_id 设置为 1,然后重置父表的自动增量计数器(以便下一个插入将具有 id = 1),它可以工作!但这不是解决方案。
如果子表中没有相关行,我看不到插入阻塞的实用性...
我只是想建立一个一对多的关系......
(我知道我可以使用 JOIN,但我正在尝试使用表关系,以实现数据完整性以及作为 php 的元数据)
【问题讨论】:
【参考方案1】:看起来您的引用表和被引用表是相反的。你可能想做:
ALTER TABLE `child ` ADD FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`);
也可以在CREATE TABLE
语句中定义外键,如下:
CREATE TABLE `parent` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `child` (
`parent_id` int(11) DEFAULT NULL,
`related_ids` int(11) DEFAULT NULL,
KEY `parent_id` (`parent_id`),
KEY `related_ids` (`related_ids`),
FOREIGN KEY (`parent_id`) REFERENCES `parent`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
测试用例:
INSERT INTO parent (`data`) VALUES ('test data 1');
Query OK, 1 row affected (0.01 sec)
INSERT INTO parent (`data`) VALUES ('test data 2');
Query OK, 1 row affected (0.01 sec)
INSERT INTO child (`parent_id`, `related_ids`) VALUES (1, 100);
Query OK, 1 row affected (0.01 sec)
INSERT INTO child (`parent_id`, `related_ids`) VALUES (2, 100);
Query OK, 1 row affected (0.01 sec)
INSERT INTO child (`parent_id`, `related_ids`) VALUES (3, 100);
ERROR 1452 (23000): Cannot add or update a child row:
a foreign key constraint fails
【讨论】:
+1:当我阅读您的回答时,我意识到我误读了问题。 感谢您的快速回答。我自己才意识到这一点! 我已经在 SQL Server 2012 中定义了身份,但我正在尝试将一些值传递给 db。那么在那个地方(自动递增)我需要通过什么?? 好的,明白了。但是在创建具有一对一关系的表时如何解决这个问题,并且您想使用ON DELETE CASCADE
以便在删除 child 时也删除父级?甚至两种方式(如果删除子项,则删除父项;如果删除父项,则删除子项)。我猜外键约束是不可能的,并且将它们与一对一的表关系一起使用是没有意义的。【参考方案2】:
呃……我想我把它弄反了。 看来我需要将外键添加到子表中,如下所示:
ALTER TABLE `child` ADD FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`);
我很难处理 mysql 术语。你能怪我吗?
【讨论】:
很高兴您意识到问题所在。如果你仔细想想,这并不难理解。外键是一个约束。您将在child
表上添加约束,因为child
表的parent
字段将被限制为仅当该值存在于parent
的id
列中时才接受该值表。以上是关于如何将自动递增的主键也用作外键?的主要内容,如果未能解决你的问题,请参考以下文章