sql - 如何每12小时执行一次 Action ?

标签 sql postgresql

我的订单表ord如下:

orderid orderstatus orderdate                          num
12         2         2015-09-01 17:23:58.189171         0
13         1         2015-09-01 17:25:12.237141         0

我需要编写一个函数来获取 orderstatus = 2 中的所有订单,并每 12 小时插入表 A 一次。问题是我希望每 12 小时执行一次插入操作...num 表示我向表 A 插入了多少次。

所以基本上它应该有这样的逻辑:

time passed < 12     num = 0  OK.
12<time passed<24    num = 0  do insert to table A.  num = 1 OK.
24 time passed<36    num = 1  do insert to table A.  num = 2 OK.
.... 

我编写了以下代码,该代码将每小时调用一次以检查是否需要完成插入:

CREATE OR REPLACE FUNCTION func()
  RETURNS void AS
$BODY$
declare
    ROW record;
    v_time int;
begin   
for row in 
    Select  orderid,orderdate,num
    From ord
    where orderstatus=2
loop 

    SELECT (extract(epoch from localtimestamp - ROW.orderdate::timestamp)/3600)::integer into v_time;

     if.........
         insert into A
         update ord set num = num+1 where orderid=ROW.orderid

end loop;
return;   
end;
$BODY$
  LANGUAGE plpgsql VOLATILE

问题是我不知道如何在函数中编写if

知道如何编写条件吗?

最佳答案

我并不真正使用 Postgres,我使用 SQL Server,但似乎它们都支持类似的功能集,因此我会将 SQL Server 的操作方式“转换”为 Postgres 语法。我最终可能会遇到一些语法错误。

主要思想

  • 您实际上并不需要显式的 IF,也不需要在循环中逐一处理各个行。在 UPDATE 语句的基于集合的 WHERE 条件中执行必要的检查。

  • 不要使用 num 列,而是使用 last_inserted_datetime 列来保存上次插入的时间戳。最初它将是NULL

  • 有一个基于集合的 UPDATE 语句,可以在 12 小时内根据需要多次运行,但实际上只有当 12 小时时,它才会更改 last_inserted_datetime几个小时过去了。如果您出于某种原因在超过 24 小时内根本没有运行此语句,它仍然可以,它会以 12 小时为增量进行UPDATE。因此,如果该过程没有运行(例如 37 小时),只需运行 3 次即可 catch 。

  • 使用RETURNING子句,在一条语句中对 ord 表执行 UPDATE 操作,并在 A 表中执行 INSERT 操作,且仅当 UPDATE 实际上更改了任何行。目前尚不清楚您到底要在 A 中插入什么内容。根据需要调整下面的查询。

将此查询放入存储过程中并安排其定期运行(例如,每小时一次或更频繁)。

WITH CTE AS
(
    UPDATE ord
    SET last_inserted_datetime = 
        COALESCE(last_inserted_datetime, orderdate) + interval '12 hours'
    WHERE
        orderstatus = 2
        AND (now() - COALESCE(last_inserted_datetime, orderdate)) > interval '12 hours'
    RETURNING orderid, orderdate, last_inserted_datetime
)
INSERT INTO A (orderid, orderdate, last_inserted_datetime)
SELECT orderid, orderdate, last_inserted_datetime
FROM CTE
;

让我们看看它是如何工作的。我们从这个 ord 表开始:

orderid orderstatus orderdate                   last_inserted_datetime
12      2           2015-09-01 17:23:58.189171  NULL
13      1           2015-09-01 17:25:12.237141  NULL

now2015-09-01 18:00:00,然后我们运行上面的查询。 noworderdate 之间的差异不到 12 小时,因此不会更新任何行,也不会将任何行插入到 A 中。

等到now2015-09-02 06:00:00,然后运行上面的查询。对于 orderid=12nowCOALESCE(last_inserted_datetime, orderdate) 之间的差异超过 12 小时,因此该行将被更新。

last_inserted_datetime = 2015-09-01 17:23:58.189171 + 12 hrs = 2015-09-02 05:23:58.189171

请注意,last_inserted_datetime 未设置为 now,而是设置为 orderdate 加 12 小时。

ord 表变为:

orderid orderstatus orderdate                   last_inserted_datetime
12      2           2015-09-01 17:23:58.189171  2015-09-02 05:23:58.189171
13      1           2015-09-01 17:25:12.237141  NULL

Plus one row is inserted into `A`.

等到现在2015-09-02 18:00:00,然后运行上面的查询。对于 orderid=12nowCOALESCE(last_inserted_datetime, orderdate) 之间的差异超过 12 小时,因此该行将被更新。

ord 表变为:

orderid orderstatus orderdate                   last_inserted_datetime
12      2           2015-09-01 17:23:58.189171  2015-09-02 17:23:58.189171
13      1           2015-09-01 17:25:12.237141  NULL

Plus one row is inserted into `A`.

假设调度程序失败了两天,直到 now2015-09-04 18:00:00 才执行查询。

ord 表变为:

orderid orderstatus orderdate                   last_inserted_datetime
12      2           2015-09-01 17:23:58.189171  2015-09-03 05:23:58.189171
13      1           2015-09-01 17:25:12.237141  NULL

Plus one row is inserted into `A`.

请注意,last_inserted_datetime 仅增加了 12 小时。再次运行查询,它将一次又一次地递增,直到 catch 当前时间。因此,不会错过任何更新/插入。

关于sql - 如何每12小时执行一次 Action ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32345609/

相关文章:

mysql - 如何将日期时间设置为零

django - 用 Django 的 Postgres 全文搜索匹配一个或多个关键字

postgresql - 从开始时间戳开始每 3 分钟选择一次数据

mysql - 没有显示我需要的结果

php - 扩展我在数据库编程方面的知识

arrays - Postgres - 通过 SQL 插入一个 varchar 数组

sql - WHERE 语句在左外连接中的位置

json - 选择数据作为 JSONB,其中值用作 json 键

mysql - SQL Workbench 逆向工程数据库 - 建立太多连接

php - 在一个查询 PDO 中选择两个表