如何在postgreSql中创建一个表,该表将在创建日期3个月后自动删除其记录?

问题描述 投票:0回答:3

我需要插入新记录并在创建日期后 3 个月删除该记录。 我将创建一个新表。 我希望该查询将创建表并自动删除创建日期超过 3 个月的记录。

sql postgresql stored-procedures triggers procedure
3个回答
2
投票

这听起来像是一个 维护任务 - 已经建议的 cron 作业通常是最合适的。

  1. 如果您可以自由使用扩展程序 - 考虑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 $$
       );    
    
  2. 否则,请将脚本保存到文件中并将其提供给常规

    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
    

还有一个话题是你的规则有多严格:

  1. 如果记录可以是 3 个月前,+/- 1 天,则每日 cron/pg_cron 作业就足够了。你的容忍度越低,你的 cron 就越频繁地重复清理工作。在某些时候,如果它在所有或大部分时间都有效运行,它可能会变得不切实际。下一个清理任务可能会在之前的清理任务完成之前开始,从而导致队列不断增长。

  2. 如果您绝对不能拥有超过 3 个月的记录,但当您已经删除了 3 个月后一天的内容时,这是可以容忍的,您可以更改 cron 作业以提前一天删除记录

    -('3 months'::interval-'1 day'::interval)

  3. 如果您被允许拥有这些记录,只是不再允许显示过时的记录 - 将表隐藏在视图后面,该视图会过滤掉所有早于 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
    甚至触发器运行清理任务,但频率较低。

  4. 如果您不能拥有超过 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 队列中出来。

“3个月”有多长

如果您指的是 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

0
投票

最好的方法是使用 cron-jobs 运行查询或使用线程在特定时间间隔运行查询。您可以使用 js 或 python 中的线程以及 golang 中的 go 例程来执行类似的任务


-1
投票

您应该在服务器上设置 cron 作业,这是最好的方法。

© www.soinside.com 2019 - 2024. All rights reserved.