Perl-不要发送双SQL请求

时间:2018-11-09 09:02:14

标签: sql perl request

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

请求是“ 2018-03-15 12:30:00”,“指标A”,62岁,我只想发送一次且不发送更多:

在我的mariadb 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密码:

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;

我的日志文件:

Wed Oct 17 04:57:08 2018 : Resource = 'toto' cstep= 'titi' time =23.634s 
Wed Oct 17 04:57:50 2018 : Resource = 'toto' cstep= 'titi' time =22.355s 

感谢您的答复

1 个答案:

答案 0 :(得分:3)

在评论中,您这样说:

  

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

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

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

您的现有代码没有任何问题。它正在按照您要求的去做。只是不够聪明。您需要使其更聪明。您有几种选择。

  1. 从日志文件中删除已处理的记录。这样,您只需将每个记录插入一次。
  2. 向您的日志文件中的每个记录添加一个标志,表明它已被添加到数据库中。然后,您可以在处理文件时检查该标志,并仅插入没有该标志的记录。
  3. 向表中添加索引,以确保它只能包含每个记录的一个副本。然后,您需要更改代码,以使其忽略从数据库中获取的所有重复数据错误。
  4. 使用REPLACE代替INSERT,并确保表上具有正确的主键,以确保不会插入重复的记录。

在不了解有关特定应用程序的日志的情况下,很难知道这些选项中的哪一个是最适合您的方法。我怀疑您会发现REPLACE选项最容易实现。

更新:我希望您会发现一些对代码有用的一般注释。

您打开文件的代码当然可以工作,但是与当前的最佳做法有些距离。我建议a)使用词法文件句柄,b)使用open()的三参数版本,c)检查调用的返回值。

open my $fh, '<', 'logfile'
  or die "Could not open 'logfile': $!\n";

使用名为$word1$word2等的变量是一个糟糕的主意。更好的主意是使用数组:

my @words = split ' ',

如果您确实想要单个变量,请给它们更好的名称:

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):

$mon = sprintf '%02d', $months{$mon}
  or die "$mon is not a valid month\n";

但是,实际上,您应该使用Time::Piece之类的东西来处理日期和时间。

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;