2013-03-13 107 views
2

我想打一个关系表用Perl这两个表之间并在其中插入数据:用Perl DBI模块关系表

$create_query = qq{ 
    create table article(
     id_article int(10) auto_increment NOT NULL, 
     url MEDIUMTEXT COLLATE utf8_general_ci, 
     html_extr_text TEXT COLLATE utf8_general_ci, 
     concord_file TEXT COLLATE utf8_general_ci, 
     sys_time VARCHAR(50), 
     primary key (id_article) 
     ) 
}; 
$dbh->do($create_query); 

$create_query = qq{ 
    create table event(
     id_event int(10) auto_increment NOT NULL, 
     event MEDIUMTEXT COLLATE utf8_general_ci, 
     primary key (id_event) 
     ) 
}; 
$dbh->do($create_query); 

现在的关系表如下:

$create_query = qq{ 
    create table article_event_index(
     id_article int(10) NOT NULL, 
     id_event int(10) NOT NULL, 
     primary key (id_article, id_event), 
     foreign key (id_article) references article (id_article), 
     foreign key (id_event) references event (id_event) 
     ) 
}; 
$dbh->do($create_query); 

有人知道为了填充'article_event_index'表应该是什么perl语句? 因为我使用数组为它看起来像这样每个表中的其他表:

my $i_event; 
my $id_event = 0; 
my @event_index; 
for ($i_event = 0; $i_event < @event_prepare; $i_event++){ 
    $dbh->do(" 
     INSERT INTO `event`(`id_event`, `event`) 
     VALUES ('$id_event', '$event_prepare[$i_event]') 
     ") || die $dbh->errstr; 
    push @event_index, $i_event; 
} 
$id_event++; 

在这种情况下,“id_event”是由$ id_event的增量产生。如果我想在索引表中重用此ID,这是一个很好的做法吗?

回答

0

由于id_event字段被定义为auto_increment,您可以让数据库为您生成id值,这是我通常如何避免竞争条件的机会。 (即,如果两个单独的用户/进程试图同时插入行并且都生成相同的id值,那么提交第二个将失败。)

插入一行后,可以使用DBI的last_insert_id方法获得价值新行自动生成的ID,如果你需要它用作另一个表的外键:

my $id = $dbh->last_insert_id(undef, undef, 'event', 'id_event'); 
+0

是的,whit'last_insert_id'方法我得到了id的列表。但是,如何在“文章”和“事件”之间建立一对多的关系?因为一篇文章可能有多个事件。所以它会是:1 - 1,1 - 2,2 - 3,2 - 4,2 - 5 ...等等。第一个数字是文章,第二个是事件。再次感谢 – user2007958 2013-03-13 09:30:57

+3

一对多关系在这里由你如何填充表格来定义。如果在你的映射表上,你插入相同的偶数id,几个文章ID(这是你的映射表定义允许的),你有一个一对多的关系。我觉得你正在寻找一种'神奇'的方式来创建一对多的关系,而无需处理idx和交叉表。你应该看看'DBIx :: Class',它可以让你这样做(但是比API更复杂的API)。 – Mattan 2013-03-13 09:37:30

1

除了戴夫Sherohman的回应,这里是你的代码的一些意见:

您应该考虑使用准备好的声明进行插入:

my $sth = $dbh->prepare("INSERT INTO `event`(`id_event`, `event`) VALUES (?,?)"); 

然后在你的循环,你可以只是这样做的每一行,你需要插入:

$sth->execute($id_event, $event_prepare[$i_event]); 

这是简单(它为您处理引用),安全(防止SQL注入),和更快。

此外,你不需要使用C风格for循环只是为了通过一个数组。您可以使用这些形式之一:

for my $i_event (0..$#event_prepare){ 
    #if you need the array index. 
} 

for my $event (@event_prepare) { 
    #if you don't need the array index. 
} 

而且,这仅仅是一个喜好,但我不喜欢{ ... }作为字符串分隔符,因为它们看起来太像代码块。