我正在尝试在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));
给了我预期的结果。
我很沮丧。
答案 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
参数默认为当前时间。但是,我可能会编写并准备一个单独的查询。