perl-在数据库中发送多个请求

时间:2019-01-04 15:57:56

标签: mysql sql perl mariadb

我在perl中有此脚本,该程序解析日志文件并将结果发送到数据库中,我的难题是我的脚本仅插入一个请求,我需要插入多个请求:

#Connect to the database.
my $dbh = DBI->connect("DBI:mysql:database=database;host=IP",
"hostname", 'password',
{'RaiseError' => 1});



while (my ($user, $ref) = each %counts) {
  while (my ($program, $count) = each %$ref) {
    #print "$count OSUSER with session $user and with program $program\n";
    print "time = $time, count = $count, user = $user, program = $program, last_line = $last_line\n";

    $request ="'$time', '$count', '$user', '$program', $last_line";

    my $sth = $dbh->prepare("REPLACE `test` (time, nb, os_name, program, last_line) VALUES($request);")
    or die "prepare statement failed: $dbh->errstr()";

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

我的日志:

       ID USER                    TERMINAL        SERVICE                    
---------- ------------------------- --------------- -------------------------  
         1 toto                    titi     roro          
         2 toto                    titi     roro          
         4 gigi                    gege        fefe      

我的数据库:

+----+---------------------+-----------+-------------+----------------+-----------+
| ID | time                | nb        | os_name     | program        | last_line |
+----+---------------------+-----------+-------------+----------------+-----------+
| 15  | 2019-01-04 14:00:00|        33 | titi        | roro           | 109       |

我想要:

+----+---------------------+-----------+-------------+----------------+-----------+
| ID | time                | nb        | os_name     | program        | last_line |
+----+---------------------+-----------+-------------+----------------+-----------+
| 15  | 2019-01-04 14:00:00|        33 | titi        | roro           | 109       |
| 16  | 2019-01-04 14:00:00|        9  | gege        | fefe           | 109       |      

(由Dave Cross添加-从注释复制。这是表定义。)

CREATE TABLE test (
  ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
  time datetime NOT NULL,
  nb int NOT NULL,
  os_name nvarchar(100) NOT NULL,
  program nvarchar(100) NOT NULL,
  last_line nvarchar(100)NOT NULL,
  PRIMARY KEY (ID),
  UNIQUE KEY (time)
) ENGINE=InnoDB;

2 个答案:

答案 0 :(得分:0)

您的表定义(通过注释)包括以下内容:

UNIQUE KEY (time)

因此,您的表只能包含一行time的任何值。

此外,您在SQL中使用REPLACE。因此,当您第二次运行语句时,数据库会看到存在具有相同唯一键的行,因此它将更新该行,而不是插入新行。

在我看来,您的代码正在按预期运行。如果要添加更多行,则需要更改$time中的值。

更新

摘自您对另一个答案的评论。

  

我用INSERT测试过,但是不起作用:DBD :: mysql :: st执行失败:重复输入'2019-01-04 17:45:00'作为密钥'time'

是的!那正是应该发生的事情。通过将time列声明为UNIQUE,您是在告诉数据库,每个时间值只能在表中出现一次。因此,如果您尝试同时插入另一行(您正在执行的操作),则会收到该错误。

因此,您从INSERT切换到REPLACE并不会出错,但是只插入了一行-因为REPLACE就是这样做的。

您在表中给出的示例在time列中具有两个相同的值。当您在该列上具有UNIQUE定义时,就不会发生这种情况。正是UNIQUE键可以防止出现的错误。

您需要退后一步,仔细考虑表中想要的内容。如果要在表中重复时间值,则需要删除表上的UNIQUE键定义(然后将REPLACE更改为INSERT)。

答案 1 :(得分:0)

来自manual for REPLACE

  

REPLACE的工作原理与INSERT相似,不同之处在于,如果表中的旧行与PRIMARY KEY 或{{1} }索引,则在插入新行之前删除旧行

(强调:我)

那里有。您有两次相同的时间UNIQUE2019-01-04 14:00:00将第二个删除时,第一个被删除

尝试删除REPLACE上的唯一索引。