如何在 PostgreSQL PLPerl 函数中进行 date/time 操作

How to do date/time manipulations in PostgreSQL PLPerl function

在用 plperl 编写 Postgres 函数(存储过程)时,我了解到无法加载 "use Time::Piece;" 等 perl 模块。鉴于此,在 plperl 中处理 date/time 操作和比较的最佳方法是什么?使用 plperlu 和加载模块不适合我。

我不得不求助于以下查询:

$query = "SELECT extract(day from timestamp '$eventDate') AS day,
                 extract(month from timestamp '$eventDate') AS month,
                 extract(year from timestamp '$eventDate') AS year";

我还使用 SQL 将时间戳转换为纪元时间,以便在 perl 中进行比较。我希望这是一个愚蠢的问题,并且有更直接和简单的方法来处理 date/time 功能。 谢谢

几乎任何 Postgres 数据库框架都会自动为您转换 Date 和 DateTime 数据类型。并且在将这些类型插入到 Postgres 中时,如果它们没有自动转换,那么 UTC 格式始终是 Postgres 可以理解的格式。

更新

根据随后的评论,我只能参考记录完备的 Date/Time 函数列表,因为问题中没有具体说明所需的操作类型:Postgres Date/Time Functions and Operators

没有简单的方法可以做到这一点。您有四个基本选项,使用哪个取决于您的具体情况。

  1. 在您的存储过程中使用 SQL。

    这通常比我喜欢的更冗长,但它可能是最简单和最有效的。示例:

    my $now = spi_exec_query('SELECT EXTRACT(epoch FROM NOW())')->{rows}[0]->{date_part}
        || die "Unable to determine current time";
    

    或者一次有多个值:

    my $row = spi_exec_query('SELECT EXTRACT(...) AS a,EXTRACT(...) AS b,... AS x')->{rows}
        or die "Some useful message...";
    my $a = $row->{a};
    my $b = $row->{b};
    ...
    my $x = $row->{x};
    
  2. 用 SQL 或 plpgsql 存储过程包装你的 plperl SP,它传递所需的日期值:

    CREATE FUNCTION foo AS $$
        SELECT foo_pl(EXTRACT(...),EXTRACT(...),...)
    $$ LANGUAGE SQL;
    
  3. 在 perl 中手动进行日期操作。

    这通常很丑陋(以及为什么日期操作模块首先存在!)但可能适用于足够简单的操作,其中闰年、时区等无关紧要(将一个小时或一天添加到时间跨度等)。

  4. 需要更复杂的perl模块,例如DateTime

    这通常需要使用 plperlu,而不是标准的 plperl,后者可能会带来一些安全问题。将如此大的模块加载到存储过程中也不太可能提高性能。但是如果你有足够的系统内存,并且你对 plperlu 的安全问题感到满意(不在此 post 中),它可以是一个选项。