简体   繁体   中英

Postgresql procedure - update and return updated records

I'm trying to write a simple procedure that will work like a queue - lock records (10 minutes) , and return those locked records.

CREATE OR REPLACE FUNCTION select_queue(
    i_limit integer,
    i_sessionid text)
  RETURNS RECORD AS
 $BODY$
 declare match_ret record;
 BEGIN

 SELECT userid,date,description INTO match_ret FROM table
 WHERE (lock_session IS NULL AND lock_date IS NULL) OR lock_date < NOW() - INTERVAL '10 MINUTE' LIMIT i_limit FOR UPDATE;

 UPDATE table SET lock_session=i_sessionid, lock_date=NOW() WHERE userid=match_ret.userid;

 RETURN match_ret;
 END;
 $BODY$
 LANGUAGE plpgsql

I'm a MySQL user and things aren't working as I would expect them to. Any help will be appreciated.

using RETURNS RECORD (unknown record) is not practical. Use a OUT variables instead. Next - you modify i_limit rows, but you return only one value. Maybe you want to return all.:

CREATE OR REPLACE FUNCTION select_queue(i_limit int,i_sessionid text,
                                        OUT o_userid int, OUT o_date, o_desc text) 
   RETURNS SETOF RECORD AS $$
DECLARE _row_id int;
BEGIN
   FOR _row_id, o_userid, o_date, o_desc IN
             SELECT row_id, userid,date,description 
                FROM table
               WHERE (lock_session IS NULL AND lock_date IS NULL) 
                  OR lock_date < NOW() - INTERVAL '10 MINUTE' 
               LIMIT i_limit FOR UPDATE
   LOOP
      UPDATE table SET lock_session=i_sessionid, lock_date=NOW() 
         WHERE row_id = _row_id;
      RETURN NEXT;
   END LOOP;
   RETURN;
END
$$ LANGUAGE plpgsql;

You can call this function with SELECT :

SELECT * FROM select_queue(10, 'safdsdfsfds');

After one day with PostgresSQL, this is what i've created:

 CREATE OR REPLACE FUNCTION api.get_user_photo(
    IN i_limit integer,
    IN i_sessionid text,
    IN i_main integer,
    OUT list refcursor,
    OUT elapsed real,
    OUT all_count integer,
    OUT userids bigint[])
  RETURNS record AS
$BODY$
DECLARE
    _tstart       timestamp with time zone;
    _max_date     timestamp with time zone;
    _ids      bigint[];
    _locked       integer;
BEGIN
    _tstart = clock_timestamp();
    _max_date = NOW() - INTERVAL '5 MINUTE';

    -- check for already locked photo
    SELECT count(1) INTO _locked FROM core.user_photos
        WHERE lock_sessionid=i_sessionid;

    IF _locked <> 0 THEN
        i_limit = i_limit - _locked;
    END IF;

    UPDATE core.user_photos
    SET lock_sessionid=i_sessionid, lock_date=NOW() 
    WHERE id in (
        SELECT id FROM core.user_photos
        WHERE (lock_sessionid IS NULL AND lock_date IS NULL AND main=i_main) 
        OR (lock_date < _max_date AND main=i_main) 
        LIMIT i_limit
    );  

    -- Count locked records
    SELECT count(1) INTO all_count
    FROM core.user_photos
    WHERE lock_sessionid=i_sessionid;

    -- Get unique ids
    SELECT array_agg(distinct userid) INTO userids
    FROM core.user_photos
    WHERE lock_sessionid=i_sessionid;

    -- Get locked photo
    OPEN list FOR
        SELECT id AS moderation_id,userid,description,md5,ext,transform,main_moderation,moderation,desc_moderation
        FROM core.user_photos
        WHERE lock_sessionid=i_sessionid;

    elapsed := EXTRACT('epoch' FROM clock_timestamp() - _tstart)::real;
    RETURN;
END
$BODY$
  LANGUAGE plpgsql

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM