考虑以下设计示例,其中 FOREST 包含 TREE (s)且 TREE (s) BRANCH (ES)。此外 FLOCK (s)包含 BIRD (s), BIRD (s)可能包含也可能不包含 BRANCH
CREATE TABLE 'FOREST' (
forest_id INT(11) NOT NULL AUTO_INCREMENT,
'name' VARCHAR(45) NOT NULL,
...
)
CREATE TABLE 'TREE' (
'tree_id' INT(11) NOT NULL AUTO_INCREMENT,
'forest_id' INT(11) NOT NULL ,
'tree_loc_x' INT NOT NULL,
'tree_loc_y' INT NOT NULL,
...
CONSTRAINT 'fk_tree_forest'
FOREIGN KEY ('forest_id' )
REFERENCES `FOREST` ('forest_id' )
)
CREATE TABLE 'BRANCH' (
'branch_id' INT(11) NOT NULL AUTO_INCREMENT,
'tree_id' INT(11) NOT NULL,
'br_loc_x' INT NOT NULL,
'br_loc_y' INT NOT NULL,
'br_loc_z' INT NOT NULL,
...
CONSTRAINT 'fk_branch_tree'
FOREIGN KEY ('tree_id' )
REFERENCES `TREE` ('tree_id' )
)
CREATE TABLE 'FLOCK' (
'flock_id' INT NOT NULL AUTO_INCREMENT ,
'name' VARCHAR(45) NOT NULL
...
)
CREATE TABLE 'BIRD' (
'bird_id' INT(11) NOT NULL AUTO_INCREMENT ,
'flock_id' INT(11) NOT NULL ,
'branch_id' INT(11) NULL ,
'bird_tag' VARCHAR(45) NOT NULL ,
...
CONSTRAINT 'fk_bird_flock'
FOREIGN KEY ('flock_id' )
REFERENCES 'FLOCK' ('flock_id' )
CONSTRAINT 'fk_bird_branch'
FOREIGN KEY ('branch_id' )
REFERENCES 'BRANCH' ('branch_id' )
)
我想从C ++应用程序加载批量类型加载(多插入语句或LOAD DATA INFILE)的每个表。
检索数据库的最佳方法是分配auto_increment值,以用作每个后续表加载的外键。
请注意,表格不一定以级联方式加载(即BIRDS将在FLOCKS之后加载,而不是直接在BRANCHES之后加载,因此“LAST_INSERT_ID”在加载BANDDS时不会对BRANCHES有用。)
每个表都有候选自然键,但我试图避免将它们用作主键或外键。
答案 0 :(得分:0)
当您使用LOAD DATA INFILE(或其他多行INSERT,如INSERT ... SELECT)时,后续对LAST_INSERT_ID()的调用仅返回生成的第一个 id值。但是InnoDB将id分配为一个连续的块,所以如果你插入了1000行,而LAST_INSERT_ID()报告了1234,那么你知道数据加载使用的是id的1234到2233.
(假设auto_incrment_increment = 1;如果不是,那么说你的数据加载将使用下一个连续的1000个id更准确。)
但是如果然后在树之后批量加载分支,则存在不知道每个分支属于哪个树的问题。有些树可能只有一个分支,有些树有六个等等。仅仅因为你有1000棵树和1000个分支,你不一定能假设均匀分布。如果你在树枝上有鸟等,它会变得更加复杂。
最终,将数据批量加载到多个表中并保留所有相应的生成ID是不切实际的。您必须编写代码以逐行循环遍历所有输入文件,并逐行捕获LAST_INSERT_ID()以在相关行中使用。我还没有找到更好的解决方案。
对于鸟类对其各自的分支及其群体都有外键的更复杂的情况,您可以尝试跟踪每个分支的插入ID,并将其映射到自然键,但也许有这么多分支,将映射保留在内存中变得不切实际。在某种程度上,您会发现在插入 分支或鸡群时可以选择插入鸟类,但不能同时插入两者(因为分支和鸡群之间存在多对多关系,您可以假设他们很好地排序)。因此插入鸟类可能涉及为其分支或其群体留下NULL,然后您必须稍后使用UPDATE填写缺失的数据。