在Perl中PostgreSQL中参数化时间戳引用的问题

时间:2013-10-17 18:23:28

标签: sql perl postgresql

我正在尝试在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

据我所知,自7.2以来,PG一直没有支持current,但我没有使用它。我正在使用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));

给了我预期的结果。

我很沮丧。

2 个答案:

答案 0 :(得分: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));

答案 1 :(得分: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参数默认为当前时间。但是,我可能会编写并准备一个单独的查询。