1

我正在尝试在 Perl 脚本中使用参数化查询从 Postgres 数据库中获取一些时间戳。这是一个简单的例子,仅用于教学目的。

我已将$start_date和定义$end_date为时间戳和间隔:

my $start_date = "current_timestamp - interval '6 hours'";
my $end_date = "current_timestamp";

我使用以下内容提交到数据库,$dbh之前定义过:

my $sql = "SELECT cast(? as timestamp), cast(? as timestamp)";
my $sth = $dbh->prepare($sql);
$sth->execute($start_date, $end_date);

当我这样做时,我得到一个有点令人困惑的错误。

DBD::Pg::st execute failed: ERROR:  date/time value "current" is no longer supported

我知道current自 7.2 以来 PG 不支持它,但我没有使用它。我正在使用current_timestamp支持的 AFACT。也就是说,如果我进入:psql

select (cast(current_timestamp - interval '6 hours' as timestamp), cast(current_timestamp as timestamp));

结果是我所期望的(两个时间戳,前六个小时在后者之前)。

我也可以使用now()而不是current_timestamp. 我可以通过以下方式使用它:

my $start_date = "now() - interval '6 hours'"; 
my $end_date = "now()";

当我尝试在 perl 中运行查询时,出现以下错误:

DBD::Pg::st execute failed: ERROR:  invalid input syntax for type timestamp: "now() - interval '6 hours'"

然而,查询:

select (cast(now() - interval '6 hours' as timestamp), cast(now() as timestamp));

给了我预期的结果。

我很困惑。

4

2 回答 2

5

问题是 SQL 占位符不代表表达式,而是单个值。而且那个值不能是一个函数。您可以执行以下操作:

my $start_date = "6 hours";
my $sql = "SELECT current_timestamp - cast(? as interval), current_timestamp";
my $sth = $dbh->prepare($sql);
$sth->execute($start_date);

你在 Perl 中所做的等同于在psql

select (cast('current_timestamp - interval ''6 hours''' as timestamp), cast('current_timestamp' as timestamp));
于 2013-10-17T18:38:42.190 回答
1

为了使您的查询窗口更灵活一点:

$sth = $dbh->prepare(<<__eosql);
SELECT * FROM tbl
 WHERE ts BETWEEN current_timestamp - ? * CAST('1 ' || ? AS INTERVAL)
                  AND
                  current_timestamp;
__eosql

$sth->execute(6, 'hour');
$sth->execute(10, 'day');
$sth->execute(1, 'week');
# etc.

当您引入固定时间点时,您可以做一些非常聪明... WHERE COALESCE(?, current_timestamp) ...的事情,例如记住undef参数默认为当前时间。但是,我可能会编写并准备一个单独的查询。

于 2013-10-17T20:55:38.217 回答