SQLite 中的多对多 Link Table 外键建模
Many-to-Many Link Table Foreign Key Modeling in SQLite
我在 SQLite 中有以下两个表:
CREATE TABLE `Link` (
`link_id` integer NOT NULL,
`part_id` integer NOT NULL,
CONSTRAINT `link_pk` PRIMARY KEY(`link_id`,`part_id`)
);
CREATE TABLE `Main` (
`main_id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,
`link_id` integer NOT NULL REFERENCES `Link`(`link_id`)
);
INSERT INTO `Link` (link_id, part_id) VALUES (1,10);
INSERT INTO `Link` (link_id, part_id) VALUES (1,11);
INSERT INTO `Link` (link_id, part_id) VALUES (1,12);
INSERT INTO `Link` (link_id, part_id) VALUES (2,15);
INSERT INTO `Main` (main_id, link_id) VALUES (1,1);
INSERT INTO `Main` (main_id, link_id) VALUES (2,1);
INSERT INTO `Main` (main_id, link_id) VALUES (3,2);
许多 Main
行可能引用相同的 link id,许多 Link
行可能具有相同的 link id,这样 select * from Main natural join Link where main_id=1
将return N 行,select * from Main where link_id=1
将 return K 行。 linkid很重要,原始数据每个main有1个linkid,每个link有N个part id。
使用上面的模式,由于外键约束 (foreign key mismatch - "Main" referencing "Link": INSERT INTO Main (main_id, link_id) VALUES (1,1);
),我无法在 Main
中插入任何行,大概是因为 the composite key requirement。我可以通过删除外键约束来让它工作,但显然我缺少一个约束。反转键的方向也不起作用,因为如上所述,它是多对多关系。有没有一种方法可以在 SQLite 中对此进行正确建模,并限制 Main
中的每个 link_id
在 Link
中至少存在一行?
我会提出不同的设计。
2 个实体 link_id
和 part_id
中的每一个都应该是 2 table 中的主键,例如:
CREATE TABLE Links (
link_id INTEGER PRIMARY KEY,
link_description TEXT
);
CREATE TABLE Parts (
part_id INTEGER PRIMARY KEY,
part_description TEXT
);
然后,创建上述 table 的结点 table(就像您当前的 Link
table):
CREATE TABLE Links_Parts (
link_id INTEGER NOT NULL REFERENCES Links(link_id),
part_id INTEGER NOT NULL REFERENCES Parts(part_id),
PRIMARY KEY(link_id, part_id)
);
和 table Main
:
CREATE TABLE Main (
main_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
link_id INTEGER NOT NULL REFERENCES Links(link_id)
);
所有的关系都在那里,如果你设置外键支持,你就可以保证参照完整性:
PRAGMA foreign_keys = ON;
查看简化版 demo.
我在 SQLite 中有以下两个表:
CREATE TABLE `Link` (
`link_id` integer NOT NULL,
`part_id` integer NOT NULL,
CONSTRAINT `link_pk` PRIMARY KEY(`link_id`,`part_id`)
);
CREATE TABLE `Main` (
`main_id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,
`link_id` integer NOT NULL REFERENCES `Link`(`link_id`)
);
INSERT INTO `Link` (link_id, part_id) VALUES (1,10);
INSERT INTO `Link` (link_id, part_id) VALUES (1,11);
INSERT INTO `Link` (link_id, part_id) VALUES (1,12);
INSERT INTO `Link` (link_id, part_id) VALUES (2,15);
INSERT INTO `Main` (main_id, link_id) VALUES (1,1);
INSERT INTO `Main` (main_id, link_id) VALUES (2,1);
INSERT INTO `Main` (main_id, link_id) VALUES (3,2);
许多 Main
行可能引用相同的 link id,许多 Link
行可能具有相同的 link id,这样 select * from Main natural join Link where main_id=1
将return N 行,select * from Main where link_id=1
将 return K 行。 linkid很重要,原始数据每个main有1个linkid,每个link有N个part id。
使用上面的模式,由于外键约束 (foreign key mismatch - "Main" referencing "Link": INSERT INTO Main (main_id, link_id) VALUES (1,1);
),我无法在 Main
中插入任何行,大概是因为 the composite key requirement。我可以通过删除外键约束来让它工作,但显然我缺少一个约束。反转键的方向也不起作用,因为如上所述,它是多对多关系。有没有一种方法可以在 SQLite 中对此进行正确建模,并限制 Main
中的每个 link_id
在 Link
中至少存在一行?
我会提出不同的设计。
2 个实体 link_id
和 part_id
中的每一个都应该是 2 table 中的主键,例如:
CREATE TABLE Links (
link_id INTEGER PRIMARY KEY,
link_description TEXT
);
CREATE TABLE Parts (
part_id INTEGER PRIMARY KEY,
part_description TEXT
);
然后,创建上述 table 的结点 table(就像您当前的 Link
table):
CREATE TABLE Links_Parts (
link_id INTEGER NOT NULL REFERENCES Links(link_id),
part_id INTEGER NOT NULL REFERENCES Parts(part_id),
PRIMARY KEY(link_id, part_id)
);
和 table Main
:
CREATE TABLE Main (
main_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
link_id INTEGER NOT NULL REFERENCES Links(link_id)
);
所有的关系都在那里,如果你设置外键支持,你就可以保证参照完整性:
PRAGMA foreign_keys = ON;
查看简化版 demo.