更新记录(如果存在)

时间:2014-05-28 10:55:07

标签: postgresql plpgsql postgresql-9.2

我需要定期检查表中的记录并更新它们,特别是用" payment_pending"检查记录。状态并将其更新为" payment_pending_expired"状态。但我不确定如何正确地做到这一点:

CREATE OR REPLACE FUNCTION cancel_pending_orders(user_id integer, max_day_amount_allowed integer)
  RETURNS SETOF void AS
$BODY$

BEGIN
  -- if the records exist at all...
  IF EXISTS (
    SELECT ph.id FROM payment_history as ph  
    INNER JOIN payment AS p
    ON p.id = ph.payment_id
    WHERE p.user_id = $1
    AND ph.status = 'payment_pending'
    AND ph.added_at + max_day_amount_allowed <= now()
  ) THEN
    -- make all of them status = 'payment_pending_expired'


    RETURN;
  END IF;

问题: 1)如何将max_day_amount_allowed添加到ph.added_at?如果它是文字,我可以通过以下方式完成:

....

  AND (ph.added_at + interval '30d') <= now()

但它不是文字,而是变量。

2)我如何参考找到的记录(如果存在)

....
  ) THEN
    -- make all of them ph.status = 'payment_pending_expired'
    -- but how do I refer to them?

    RETURN;

P.S。 <{1}}的类型只有ph.status而不是varchar,只是为了简单起见。

2 个答案:

答案 0 :(得分:2)

1)您需要将cast日计为间隔时间:

AND (ph.added_at + ($2 || ' days')::interval) <= now()

2)您可以使用CURSOR对结果集中的每一行执行某些操作。

但在你的情况下(如果你只想更新它们)只需使用一个UPDATE命令:

UPDATE payment_history AS ph
   SET ph.status = 'payment_pending_expired'
  FROM payment AS p
 WHERE p.id = ph.payment_id
   AND p.user_id = $1
   AND ph.status = 'payment_pending'
   AND (ph.added_at + ($2 || ' days')::interval) <= now()

答案 1 :(得分:1)

  

如何将max_day_amount_allowed添加到ph.added_at

假设timestamp的类型为 added_at

不要转换为text,连接并转换回来。只需乘以interval

ph.added_at + interval '1d' * max_day_amount_allowed <= now()

或者,如果added_at date ,您只需将integer添加到date即可。然后,日期会自动强制为时间戳(根据本地时间),以便与now()进行比较:

ph.added_at + max_day_amount_allowed <= now()