我想要的是在mysql表中插入数据,但我无法找到从一行建立关系的方法
假设我有一个文件 file.tab ,它包含类似
的数据parent_1 parent_details_1 child_1.1 child_details_1.1 child_1.2 child_details_1.2
parent_2 parent_details_2 child_2.1 child_details_2.1
parent_3 parent_details_3 child_3.1 child_details_3.1 child_3.2 child_details_3.2 child_3.3 child_details_3.3
我想要实现的是在两个表中插入数据,如
parent_table
+---+-----------+-------------------+
|id | name | details |
+---+-----------+-------------------+
| 1 | parent_1 | parent_details_1 |
| 2 | parent_2 | parent_details_2 |
| 3 | parent_3 | parent_details_3 |
+---+-----------+-------------------+
child_table
+---+-----+-----------+-------------------+
|id | pid | name | details |
+---+-----+-----------+-------------------+
| 1 | 1 | child_1.1 | child_details_1.1 |
| 2 | 1 | child_1.2 | child_details_1.2 |
| 3 | 2 | child_2.1 | child_details_2.1 |
| 4 | 3 | child_3.1 | child_details_3.1 |
| 5 | 3 | child_3.2 | child_details_3.2 |
| 6 | 3 | child_3.3 | child_details_3.3 |
+---+-----+-----------+-------------------+
前两列是父母的,之后两列是属于孩子的,但我不知道父母有多少孩子。
我试图以这种方式加载文件。
LOAD DATA INFILE '/tmp/file.tab INTO TABLE ...
但我接下来做什么我不知道。
如此善意地帮助我解决这个问题。
答案 0 :(得分:6)
创建一个包含大量列的表(Staging
)。 NULL
的空(parent_id
)列和子项的ID。
希望在LOAD DATA
期间,'短'行会在遗失的子列中放置空值。
INSERT .. SELECT ..
将parent
和parent_detail
放入Parents
表格。将ids
从Parents
拉回Staging.parent_id
。有关这两个SQL的详细信息位于http://mysql.rjweb.org/doc.php/staging_table#normalization
现在为每个可能的“子”列集做类似的事情:child1
和child1_detail
(可能是NULL对)和当前的NULL child1_id
。同样适用于child2 *等。请注意,在填充Children
表时,您已经有parent_id
可用。
这是执行任务的全SQL方式。它只比编写Perl / PHP / Java / VB /任何代码来执行任务稍微麻烦一点。
答案 1 :(得分:1)
假设Child和Parent都是Person,我只创建一个Person表,id_parent是可选的。
CREATE TABLE person (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) DEFAULT NULL,
details varchar(255) DEFAULT NULL,
id_parent1 int(11) DEFAULT NULL,
id_parent2 int(11) DEFAULT NULL,
PRIMARY KEY (id)
);
如何加载数据非常依赖于您喜欢的语言。 Load data infile
需要静态结果表。
您拥有的行数可能不同,您需要将每行作为单个列导入。然后,您可以使用存储过程迭代它:
cursors
以了解如何迭代这样的单个列临时表的每一行。 replace
,您可以计算出每行中的列数。while
循环,您可以先开始导入子项,然后再导入父项。 平心而论,这将是一个相当复杂的存储过程,对于初学者来说可能很难写。如果您熟悉任何编程语言及其连接MySQL的方法,您可以更优雅地完成这项工作。
答案 2 :(得分:0)
如果解决方案不需要全部在SQL中,我发现预处理通常更简单。在这种情况下,将数据拆分为两个文件,这些文件可以通过LOAD DATA INFILE轻松加载(一个用于父表,一个用于子表)。
以下是使用perl
进行预处理的一种方法my ( $parent_id, $child_id ) = ( 0, 0 );
my ( @parent_table, @child_table );
while (<>) { # for each line of input
chomp;
# split on tabs
my ( $parent_name, $parent_detail, @child_id_detail_pairs ) = split /\t/;
# create a row and parent_id for the parent table
push @parent_table, [ ++$parent_id, $parent_name, $parent_detail ];
while (@child_id_detail_pairs) { # while we have child names & details
# remove a name and details
my $child_name = shift @child_id_detail_pairs;
my $child_details = shift @child_id_detail_pairs;
# create a row and child_id for the child table
push @child_table, [ ++$child_id, $parent_id, $child_name, $child_details ];
}
}
# write this to one file to load into the parent table
print "parent_table\n";
for my $row (@parent_table) {
print join( "\t", @$row ), "\n";
}
# write this to one file to load into the child table
print "child_table\n";
for my $row (@child_table) {
print join( "\t", @$row ), "\n";
}