如何在 Postgres 函数中存储日期变量?

Posted

技术标签:

【中文标题】如何在 Postgres 函数中存储日期变量?【英文标题】:How do I store date Variable in Postgres function? 【发布时间】:2020-02-20 22:00:31 【问题描述】:

所以我正在努力创建一个函数,该函数将从表中删除价值 1 个月的记录。该表在 postgres 中。由于 postgres 没有存储过程,我试图声明一个函数,其逻辑将 1 个月的记录插入历史表,然后从活动表中删除记录。我有以下代码:

CREATE FUNCTION DeleteAndInsertTransaction(Integer)
    RETURNS Void
AS $Body$

SELECT now() into saveTime;

SELECT * INTO public.hist_table  
FROM (select * from public.live_table
    WHERE update < ((SELECT * FROM saveTime) - ($1::text || ' months')::interval)) as sub;

delete from public.live_table
where update < ((SELECT * FROM saveTime) - ($1::text || ' months')::interval);

DROP TABLE saveTime;     

$Body$
Language 'sql';

所以上面的代码编译得很好,但是当我尝试通过调用它来运行它时:-DeleteAndInsertTransaction(27) 它给了我一个 Error: relation "savetime" does not exist 我不知道这里发生了什么。 如果我从函数块中取出SELECT now() into saveTime; 并在调用函数之前声明它,那么它运行良好,但我需要将当前日期存储到一个变量中,并将其用作插入和删除的常量,这就是针对一个巨大的表,插入和删除之间可能存在显着的时间差异。关于这里发生了什么的任何指示?

【问题讨论】:

Postgrese 确实有存储过程:postgresql.org/docs/current/sql-createprocedure.html 但对于你想要做的事情,一个函数同样好。 “postgres 没有存储过程” ...正如 a_horse_with_no_name 评论的那样,CREATE PROCEDURE 已添加到 Postgres 11 及更高版本中。 Search to learn more,阅读this和this等帖子。 【参考方案1】:

select .. into ..create table ... as select ... 的弃用语法,creates 是一个 new 表。

所以,SELECT now() into saveTime; 实际上创建了一个新表(命名为 savetime),相当于:create table savetime as select now(); - 它没有在变量中存储任何内容。

要将值存储在变量中,您需要先declare 变量,然后才能assign 值。但是你只能在 PL/pgSQL 中做到这一点,而不是 SQL

CREATE FUNCTION DeleteAndInsertTransaction(p_num_months integer)
  returns void
as
$Body$
declare
  l_now timestamp;
begin
  l_now := now();
  ...
end;
$body$
language plpgsql;

要插入到您需要的现有表中

insert into public.hist_table  
select * 
from public.live_table.

要选择最近 x 个月的行,无需将当前日期和时间存储在变量中。使用make_interval() 来生成基于指定单位的区间也更容易。

你可以简单地使用

select *
from live_table
where updated_at <= current_date - make_interval(mons => p_pum_months);

由于您不需要变量,因此您实际上可以使用language sql 函数来完成所有这些操作。

所以函数看起来像这样:

CREATE FUNCTION DeleteAndInsertTransaction(p_num_months integer)
    RETURNS Void
AS 
$Body$

  insert into public.hist_table  
  select *
  from live_table
  where updated_at < current_date - make_interval(months => p_pum_months);

  delete from public.live_table
  where updated_at < current_date - make_interval(months => p_pum_months);

$Body$
Language sql;

请注意,语言名称是一个标识符,不应被引用。


您实际上可以在一条语句中执行 DELETE 和 INSERT:

with deleted as (
  delete from public.live_table
  where updated_at <= current_date - make_interval(months => p_pum_months)
  returning * 
)
insert into hist_table
select *
from deleted;

【讨论】:

以上是关于如何在 Postgres 函数中存储日期变量?的主要内容,如果未能解决你的问题,请参考以下文章

Postgres - 在函数之外声明变量[重复]

如何在 Postgres 函数中检索多个结果行?

Python-Sqlalchemy-Postgres:如何将子查询结果存储在变量中并将其用于主查询

如何使用 django ORM 在 postgres 中仅选择日期部分

如何在 Postgres/plpgsql 的视图定义中使用变量

如何通过 postgres 中的存储函数压缩 CSV 文件