我需要插入新记录并在创建日期后 3 个月删除该记录。 我将创建一个新表。 我希望该查询将创建表并自动删除创建日期超过 3 个月的记录。
这听起来像是一个 维护任务 - 已经建议的 cron 作业通常是最合适的。
如果您可以自由使用扩展程序 - 考虑pg_cron:
CREATE EXTENSION pg_cron;
-- Delete old data daily at 3:30am (GMT)
SELECT cron.schedule(
'delete outdated records',
'30 3 * * *',
$$ DELETE FROM new_table WHERE created_date < now()-'3 months'::interval $$
);
cron
作业
# weekdays at 01:00am
# min hour mday month wday command-to-run
0 1 * * 1-5 psql -h dbhost -p 5432 -U dbuser --dbname dbname < my.sql
还有一个话题是你的规则有多严格:
如果记录可以是 3 个月前,+/- 1 天,则每日 cron/pg_cron 作业就足够了。你的容忍度越低,你的 cron 就越频繁地重复清理工作。在某些时候,如果它在所有或大部分时间都有效运行,它可能会变得不切实际。下一个清理任务可能会在之前的清理任务完成之前开始,从而导致队列不断增长。
如果您绝对不能拥有超过 3 个月的记录,但当您已经删除了 3 个月后一天的内容时,这是可以容忍的,您可以更改 cron 作业以提前一天删除记录
-('3 months'::interval-'1 day'::interval)
如果您被允许拥有这些记录,只是不再允许显示过时的记录 - 将表隐藏在视图后面,该视图会过滤掉所有早于 3 个月的内容。 演示:
create table new_table (data text, created_date timestamp default now());
insert into new_table (data) values ('value1');
alter table new_table rename to new_table_raw;
create view new_table as
select * from new_table_raw where created_date>now()-'3 months'::interval;
--insert, update, delete still work even though it's a view now
insert into new_table (data) values ('value2');
delete from new_table where data='value2';
update new_table set data='value3' where data='value1';
这可以为您提供最高精度,且无需维护费用。它保证隐藏 3 个月前及之前(截至查询时间)的记录 - 正好是 3 个月,精确到几分之一秒。您可以保持这种感知精度,同时不太严格地遵循 3 个月的限制,使用
cron
、pg_cron
甚至触发器运行清理任务,但频率较低。
如果您不能拥有超过 3 个月的记录,并且必须保存少于 3 个月的记录,您可能需要设置一个 trigger/rule,它将在以下频道上
NOTIFY
传入记录及其计划删除时间,以及一个可以在该通道上 LISTEN
并设置 at
任务(在 Windows 上为 schtasks
)的守护程序。
at now + 3 months -f delete_older_than_3_months_using_psql.sh
该脚本可以是常规的
delete
,在某些记录过时时触发,但仍然必须搜索所有记录并找到它们,或者您可以将它们的主键保存在清理命令中或让它pop()
它从某处的 FIFO 队列中出来。
如果您指的是 90 天,则需要接受删除日期将根据创建日期的 90 天差异内的月份长度而变化。
with
test_dates(example) as
( values
('2023.01.01'::date),
('2023.02.01'::date),
('2024.02.01'::date),--leap year
('2023.03.01'::date))
select example, (example + '90 days'::interval)::date as "date 90 days later"
from test_dates;
-- example | date 90 days later
--------------+--------------------
-- 2023-01-01 | 2023-04-01
-- 2023-02-01 | 2023-05-02
-- 2024-02-01 | 2024-05-01 --leap year
-- 2023-03-01 | 2023-05-30
如果您指的是 3 个月,您需要接受有时会更长或更短的事实:
with
test_dates(example) as
( values
('2023.01.01'::timestamp),
('2023.02.01'::timestamp),
('2024.02.01'::timestamp),--leap year
('2023.03.01'::timestamp),
('2023.04.01'::timestamp),
('2023.05.01'::timestamp),
('2023.06.01'::timestamp) )
select example, example + '3 months'::interval - example as "3 months length in days"
from test_dates;
-- example | 3 months length in days
-----------------------+-------------------------
-- 2023-01-01 00:00:00 | 90 days
-- 2023-02-01 00:00:00 | 89 days
-- 2024-02-01 00:00:00 | 90 days --leap year
-- 2023-03-01 00:00:00 | 92 days
-- 2023-04-01 00:00:00 | 91 days
-- 2023-05-01 00:00:00 | 92 days
-- 2023-06-01 00:00:00 | 92 days
不同的系统和人对它有不同的解释:PostgreSQL 中的“N 个月”间隔文字:
select '01-31-2023'::timestamp + '1 month';--2023-02-28 00:00:00
select '02-28-2023'::timestamp + '1 month';--2023-03-28 00:00:00
select '02-29-2024'::timestamp + '1 month';--2024-03-29 00:00:00 --leap year
select '03-31-2023'::timestamp + '1 month';--2023-04-30 00:00:00
在 bash 中,
at
有不同的理解:
$ echo "command" | at "00:00 013123" + 1 month
job 14 at Fri Mar 3 00:00:00 2023
$ echo "command" | at "00:00 022823" + 1 month
job 15 at Tue Mar 28 00:00:00 2023
$ echo "command" | at "00:00 022924" + 1 month #leap year
job 16 at Tue Mar 29 00:00:00 2024
$ echo "command" | at "00:00 033123" + 1 month
job 17 at Mon May 1 00:00:00 2023
最好的方法是使用 cron-jobs 运行查询或使用线程在特定时间间隔运行查询。您可以使用 js 或 python 中的线程以及 golang 中的 go 例程来执行类似的任务
您应该在服务器上设置 cron 作业,这是最好的方法。