如何在 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 函数中存储日期变量?的主要内容,如果未能解决你的问题,请参考以下文章
Python-Sqlalchemy-Postgres:如何将子查询结果存储在变量中并将其用于主查询
如何使用 django ORM 在 postgres 中仅选择日期部分