Perl-don';不发送双sql请求

Perl-don';不发送双sql请求,sql,perl,request,Sql,Perl,Request,我有一个perl脚本,不想发送双重请求: 请求是'2018-03-15 12:30:00','Metric A',62,我只想发送一次,而不是更多: 在我的bdd中,我有两行: SELECT time, measurement, valueOne FROM `metric_values`; 结果: +---------------------+-----------------+----------+ | time | measurement | va

我有一个perl脚本,不想发送双重请求:

请求是'2018-03-15 12:30:00','Metric A',62,我只想发送一次,而不是更多:

在我的bdd中,我有两行:

 SELECT time, measurement, valueOne FROM `metric_values`;
结果:

+---------------------+-----------------+----------+ 
| time                | measurement     | valueOne |
+---------------------+-----------------+----------+ 
| 2018-03-15 12:30:00 | Metric A        |       62 | 
| 2018-03-15 12:30:00 | Metric A        |       62 |
我的perl scipt:

use DBI;
open (FILE, 'logfile');
while (<FILE>) {

($word1, $word2, $word3, $word4, $word5, $word6, $word7, $word8, $word9, $word10, $word11, $word12, $word13, $word14) = split(" ");

$word13 =~ s/[^\d.]//g;


    if ($word13 > 5) {

        if ($word2 eq "Jan") {

        $word2 = "01"
        }

        if ($word2 eq "Feb") {

        $word2 = "02"
        }

        if ($word2 eq "Mar") {

        $word2 = "03"
        }

        if ($word2 eq "Apr") {

        $word2 = "04"
        }

        if ($word2 eq "May") {

        $word2 = "05"
        }

        if ($word2 eq "Jun") {

        $word2 = "06"
        }

        if ($word2 eq "Jul") {

        $word2 = "07"
        }

        if ($word2 eq "Aug") {

        $word2 = "08"
        }

        if ($word2 eq "Sep") {

        $word2 = "09"
        }

        if ($word2 eq "Oct") {

        $word2 = "10"
        }

        if ($word2 eq "Nov") {

        $word2 = "11"
        }

        if ($word2 eq "Dec") {

        $word2 = "12"
        }

        print "'$word5-$word2-$word3 $word4', $word11, $word13 \n";

              }
    # Connect to the database.
    my $dbh = DBI->connect("DBI:mysql:database=db;host=ip",
                           "titi", 'mp!',
                           {'RaiseError' => 1}) ;


    my $sth = $dbh->prepare(

        "INSERT `metric_values` (time, measurement, valueOne) VALUES('$word5-$word2-$word3 $word4', $word11, $word13);")#result is ('2018-03-15 12:30:00', 'Metric A', 62)

        or die "prepare statement failed: $dbh->errstr()";
    $sth->execute() or die "execution failed: $dbh->errstr()";
    print $sth->rows . " rows found.\n";

    $sth->finish;

感谢您在评论中的回复,您可以这样说:


我每5分钟执行一次脚本,在表中创建许多相同的行,我不希望在表中出现相同的行

我认为这就是正在发生的事情

每五分钟运行一次程序。每次运行程序时,都使用与输入完全相同的日志文件。因此,每次都会处理相同的记录,并在每次运行时插入数据的新副本

您现有的代码没有问题。它正在做你要求它做的事情。这还不够聪明。你需要做得更聪明些。你有几个选择

  • 从日志文件中删除已处理的记录。这样,每个记录只插入一次
  • 向日志文件中的每条记录添加一个标志,指示该记录已添加到数据库中。然后,您可以在处理文件时检查该标志,并且只插入没有该标志的记录
  • 向表中添加索引,以确保它只能包含每条记录的一个副本。然后需要更改代码,以便它忽略从数据库返回的任何重复数据错误
  • 使用而不是插入,并确保表上有正确的主键,以确保不会插入重复记录
  • 如果不了解有关特定应用程序的更多日志,就很难知道这些选项中哪一个是最适合您的方法。我想您会发现
    REPLACE
    选项最容易实现

    更新:我希望您会发现一些关于代码的一般性评论非常有用

    当然,您打开文件的代码是有效的,但它与当前的最佳实践有一定距离。我建议a)使用词法文件句柄,b)使用三个参数版本的
    open()
    和c)检查调用的返回值

    open my $fh, '<', 'logfile'
      or die "Could not open 'logfile': $!\n";
    
    如果您确实需要单个变量,请为它们提供更好的名称:

    my ($day, $mon, $date, $time, $year, ... ) = split(' ');
    
    就我个人而言,我会把每条记录都变成一个散列

    my @cols = qw[day mon date time year ... ];
    
    # and then, in your loop
    my %record;
    @record{@cols} = split ' ';
    
    将月份转换为数字的方式很笨拙。考虑设置转换哈希。

    my %months = (
      Jan => 1,
      Feb => 2,
      ...
    );
    
    然后您的代码变成(假设
    $mon
    而不是
    $word2
    ):

    但是,实际上,您应该使用类似的方法来处理日期和时间

    my $timestamp = "$day $mon $date $time $year";
    my $tp = Time::Piece->strptime($timestamp, '%a %b %d %H:%M:%S $Y');
    say $tp->ymd, ' ', $tp->hms;
    

    您的脚本只执行一次插入。如果您多次调用它,它将执行多次插入。如果行已经存在,您实际上是在寻找一种不插入行的方法,对吗?在这种情况下可能会有所帮助。我每5分钟执行一次脚本,在表中创建许多相同的行,我不希望在表中创建相同的行在字段上创建一个唯一的索引,该索引应该是唯一的?@jack:我不确定你真正的问题是什么。这个脚本使用一个固定语句插入一行,这当然会在执行时添加数据,因为这些数据在脚本中是硬编码的。如果您打算在表中只包含这一行,那么为什么要多次执行此脚本?我向您展示了所有代码在(文本)日志文件中添加“已处理”标志可能会涉及每次重新写入整个文件(尽管有很多方法)。避免重新处理日志行的更好方法是使用File::Tail()或类似工具,这样每次新运行都可以从上一次运行结束的地方开始,而不是每次都从文件的开头开始。@DaveSherohman:我并不是说它们都是好的选项:-)
    my %months = (
      Jan => 1,
      Feb => 2,
      ...
    );
    
    $mon = sprintf '%02d', $months{$mon}
      or die "$mon is not a valid month\n";
    
    my $timestamp = "$day $mon $date $time $year";
    my $tp = Time::Piece->strptime($timestamp, '%a %b %d %H:%M:%S $Y');
    say $tp->ymd, ' ', $tp->hms;