如何从PL / pgSQL中的子选择一次更新多个记录

时间:2013-07-02 03:11:39

标签: postgresql stored-procedures postgresql-9.1 plpgsql

我有一个存储过程可行,但速度非常慢。

基本上我想要做的是在单个更新命令中更新从子查询中获得的一组行。另一个需要注意的是,我想返回我在语句中更新的行。

现在我正在使用一个循环获取单行并更新它,使用返回存储结果,这可以工作,但实际上很慢。

建议?

以下是当前工作版本以及架构创建语句。

CREATE TABLE "queued_message"
(
  id bigserial NOT NULL,
  body json NOT NULL,
  status character varying(50) NOT NULL,
  queue character varying(150) NOT NULL,
  last_modified timestamp without time zone NOT NULL,
  CONSTRAINT id_pkey PRIMARY KEY (id)
);

CREATE TYPE returned_message as (id bigint, body json, status character varying(50) , queue character varying(150), last_modified timestamp without time zone);

CREATE OR REPLACE FUNCTION get_next_notification_message_batch(desiredQueue character varying(150), numberOfItems integer) 
    RETURNS SETOF returned_message AS $$ 
    DECLARE result returned_message; messageCount integer := 1;
    BEGIN
    lock table queued_notification_message in exclusive mode;
    LOOP 
        update queued_notification_message
        set 
            status='IN_PROGRESS', last_modified=now()
        where
            id in (
            select
                id
            from
                queued_notification_message
            where
                status='SUBMITTED' and queue=desiredQueue
            limit 1
            )
        returning * into result;
        RETURN NEXT result; 
        messageCount := messageCount+1;
        EXIT WHEN messageCount > numberOfItems;
    END LOOP;   
END;$$LANGUAGE plpgsql;

1 个答案:

答案 0 :(得分:0)

很难加速代码,因为UPDATE语句不支持的LIMIT子句也是如此,可能以下示例就足够了:

CREATE OR REPLACE FUNCTION public.fx2(n integer)
 RETURNS SETOF oo
 LANGUAGE plpgsql
AS $function$
begin
  return query update oo set a = b 
                 where b in (select b 
                                from oo
                               order by b 
                               limit n) 
                 returning *;
  return;
end;
$function$

postgres=# insert into oo select 1, i from generate_series(1,100) g(i);
INSERT 0 100
postgres=# select * from fx2(1);
 a | b 
---+---
 1 | 1
(1 row)

postgres=# select * from fx2(4);
 a | b 
---+---
 1 | 1
 2 | 2
 3 | 3
 4 | 4
(4 rows)

postgres=# select * from oo limit 10;
 a | b  
---+----
 1 |  5
 1 |  6
 1 |  7
 1 |  8
 1 |  9
 1 | 10
 1 | 11
 1 | 12
 1 | 13
 1 | 14
(10 rows)