【问题标题】:perl - send multiple request in databaseperl - 在数据库中发送多个请求
【发布时间】:2019-05-31 05:21:17
【问题描述】:

我在 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;

【问题讨论】:

  • 你为什么使用REPLACE 没有WHERE 子句?
  • 另外,为什么不在循环前做好准备并在执行中使用占位符?
  • 用替换我可以添加更多请求
  • 使用占位符值。您不能只在查询中插入原始字符串。
  • VALUES($request) 说你没有使用占位符。我可以在前面的行中看到您刚刚将数据拍入 没有转义 这是一个huge problem

标签: mysql sql perl mariadb


【解决方案1】:

您的表定义(来自评论)包括:

UNIQUE KEY (time)

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

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

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

更新:

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

我使用 INSERT 进行了测试,但不起作用:DBD::mysql::st 执行失败:重复条目 '2019-01-04 17:45:00' for key 'time'

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

因此,您从 INSERT 切换到 REPLACE 并没有收到任何错误,但只插入了一行 - 因为这是 REPLACE 所做的。

您在表中给出的示例在时间列中有两个相同的值。当您在该列上有 UNIQUE 定义时,这不会发生。这正是 UNIQUE 键可以防止的。

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

【讨论】:

    【解决方案2】:

    来自manual for REPLACE

    REPLACE 的工作方式与INSERT 完全相同,只是如果表中的旧行与PRIMARY KEY UNIQUE 索引的新行具有相同的值,则删除旧行在插入新行之前

    (重点:我)

    你有它。你有相同的时间2019-01-04 14:00:00 两次。当REPLACE第二个时,第一个被删除

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

    【讨论】:

    • 我使用 INSERT 进行了测试,但不起作用:DBD::mysql::st 执行失败:在 test2 中,键“时间”的重复条目“2019-01-04 17:45:00”。 pl line 83, line 181. DBD::mysql::st execute failed: Duplicate entry '2019-01-04 17:45:00' for key 'time' at test2.pl line 83, 第 181 行。
    • @jack94 你明白unique key (time) 是做什么的吗?如果您想要更多行,则需要它们具有不同的时间戳。或者,从表中删除 unique key(time) 约束。
    猜你喜欢
    • 1970-01-01
    • 2019-12-11
    • 2019-03-04
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2022-07-26
    相关资源
    最近更新 更多