【问题标题】:Passing psql query from perl into string将 psql 查询从 perl 传递到字符串
【发布时间】:2013-01-15 13:43:43
【问题描述】:

目前我有一个 perl 脚本,它可以访问我们的数据库、执行某些查询并将输出打印到终端。相反,我想在生成 pdf 之前将结果输出到模板乳胶文件中。对于我的大多数查询,我提取数字并将它们存储为标量变量(例如,特定操作员执行给定任务的频率)。例如。

foreach $op (@operator) {
    $query = "SELECT count(task_name) FROM table WHERE date <= '$date_stop' and 
              date >= '$date_start' and task=\'$operator[$index]\';";

    #execute query
    $result=$conn->exec($query);
    $conres = $conn->errorMessage;
    if ($result->resultStatus eq PGRES_TUPLES_OK) {
        if($result->ntuples > 0) {
            ($task[$index]) = $result->fetchrow;
        }
        printf("$operator[$index] carried out task: %d\n", $task[$index]);   
    } else {
        die "Failed.\n$conres\n\n";
        exit -1;
    }
    $index++;
} 
printf("**********************************\n\n");

在最终报告中,我将在表格中总结每个操作员完成每个任务的次数。除此之外,还有一些必须报告的事件。我可以使用诸如

之类的命令轻松地将这些打印到终端
$query = "SELECT operator, incident_type from table_name WHERE incident_type = 'Y' 
          and date <= '$date_stop' and date >= '$date_start';";
$result=$conn->exec($query);
$conres = $conn->errorMessage;
if ($result->resultStatus eq PGRES_TUPLES_OK) {
    if($result->ntuples > 0) {
        $result->print(STDOUT, 1, 1, 0, 0, 0, 1, "\t", "", "");
    }
} else {
    die "Failed.\n$conres\n\n";
    exit -1;
}

这个命令的输出示例是

operator  |   incident_type
-----------------------------
AB        |  Incomplete due to staff shortages
-------------------------------
CD        |  Closed due to weather
-----------------------------

如何让我的 perl 脚本将操作员名称和事件传递到字符串数组中,而不仅仅是将结果发送到终端?

【问题讨论】:

  • 您在使用 DBI 模块吗?您也许应该指定。
  • 看起来你甚至没有使用strict,而且你使用了printfexit 错误。然后是毫无意义的\' 和SQL 注入问题。这不让我想仔细看看。
  • Pg 模块似乎已有 13 年历史,可能不是最新的,尽管我认为它可能仍然有效。您的代码中有多个错误,所以我的建议是废弃它并重新开始,改用 DBI 模块。
  • @moadeep 你正在使用printf print 就足够了(print "*****\n\n"print "$operator[$index] carried out task: $task[$index]\n");您正在使用带有可变格式字符串的printfprintf "$operator[$index] ...",格式字符串注入错误); exit(至少在 unixish 操作系统上)只取 0 到 255 之间的值(exit -1 是无意义的)。如果你使用strict 'vars',那么你所有的变量都有一个太宽的范围(全局变量?)。你真的应该用use warnings; use strict;开始每个文件。
  • @melpomene 不要忘记在 for 循环中使用 $op,但要使用 $operator[$index] 来访问元素。而且在exit 之前使用die 也是一种毫无意义的练习。

标签: sql linux perl psql


【解决方案1】:

您应该考虑更新您的脚本以使用DBI。这是 Perl 中数据库连接的标准。

DBI 具有用于将参数插入查询字符串的内置工具。它比自己手动创建字符串更安全、更快捷。在循环之前,执行一次:

#dbh is a database handle that you have already opened.
my $query = $dbh->prepare(
    "SELECT count(task_name) FROM table WHERE date<=? and date>=? and task=?"
);

然后在循环中,你只需要每次都这样做:

$query->execute($date_stop,$date_start,$op);

请注意,您传递给execute 的参数会自动插入到您语句中的? 的位置。它为您处理报价。

同样在循环中,执行语句后,可以得到如下结果:

my $array_ref = $query->fetchall_array_ref;

现在所有的行都存储在一个二维数组结构中。 $array_ref-&gt;[0][0] 将返回第一行的第一列。

请参阅DBI documentation 了解更多信息。

正如其他人所提到的,您的代码中还有很多其他错误。请务必以use strict; use warnings; 开头,如果需要进一步帮助,请提出更多问题!

【讨论】:

  • 感谢您的回复。因为它是一个 postgreSQL 数据库,我应该使用 DBD:Pg 驱动程序连接到数据库吗?
  • @moadeep,我没有使用过 postgreSQL,但是是的,这似乎是正确的驱动程序。
【解决方案2】:

对您的脚本有很多很好的反馈,但对您的实际问题却一无所知。

如何让我的 perl 脚本将操作员名称和事件传递到字符串数组中,而不仅仅是将结果发送到终端?

您是否尝试过创建一个数组并将项目推送给它?

my @array;
push (@array, "foo");

或者使用嵌套数组:

push (@array, ["operator", "incident"]);

【讨论】:

  • 我没有,但这看起来正是我需要的。我已经接受了反馈,我目前正在从头开始重写我的脚本并尝试正确地执行它并遵循良好的 perl 约定。谢谢
  • 我的回答确实显示了如何在数组中获取查询结果(尽管使用不同的模块)。
猜你喜欢
  • 2016-05-22
  • 2015-07-11
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
相关资源
最近更新 更多