Реализовать функцию курсора в качестве разбиения на страницы в PL/pgSQL

#postgresql #plpgsql #database-cursor

Вопрос:

У меня есть таблица с более чем 1000 строками. Мне нужно получать 5 строк каждый раз, когда я вызываю функцию psql. В функции у меня будут аргументы, если аргументы пусты, она должна возвращать первые 5 строк, иначе следующие 5 строк с аргументом, который я передал

 code | title | did | date_prod | kind | len ------- ------------------------- ----- ------------ ---------- -------  BL101 | The Third Man | 101 | 1949-12-23 | Drama | 01:44  BL102 | The African Queen | 101 | 1951-08-11 | Romantic | 01:43  JL201 | Une Femme est une Femme | 102 | 1961-03-12 | Romantic | 01:25  P_301 | Vertigo | 103 | 1958-11-14 | Action | 02:08  P_302 | Becket | 103 | 1964-02-03 | Drama | 02:28  create or replace function get_giusers_batch(code)  returns void as $ declare   user_batch record;  giusers cursor   for select *  from giuser; begin  -- open the cursor  open giusers(code);     -- fetch row into the film  user_batch := fetch FORWARD 10 FROM giusers; -- exit when no more row to fetch  exit when not found;         -- close the cursor  close giusers;   return user_batch; end; $  

Комментарии:

1. Создайте курсор, затем попросите функцию извлечь 5 строк из этого курсора.

2. BEGIN WORK; DECLARE films_cur SCROLL CURSOR FOR SELECT * FROM film; -- Fetch the first 5 rows in the cursor films_cur: fetch FORWARD 10 FROM films_cur; -- Close the cursor and end the transaction: CLOSE films_cur; COMMIT WORK; @LaurenzAlbe это правильно?

Ответ №1:

Если вы хотите разбить страницу на страницы, вы имеете в виду взаимодействие с пользователем. Вы не можете держать транзакцию открытой во время этого, поэтому вам нужен WITH HOLD курсор. Для этого вам нужен динамический SQL в PL/pgSQL. Важно, чтобы курсор был явно закрыт!

Вот пример:

 CREATE FUNCTION get_data(arg integer) RETURNS SETOF uni  LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT AS $BEGIN  IF arg IS NOT NULL THEN  /* make sure cursor is closed */  BEGIN  EXECUTE 'CLOSE get_data_cur';  EXCEPTION  WHEN invalid_cursor_name THEN  NULL; /* ignore */  END;   /* declare and open cursor */  EXECUTE format(  E'DECLARE get_data_cur CURSOR WITH HOLD FORn'  'SELECT id FROM unin'  'WHERE id gt; %s',  arg  );  END IF;   /* return next five rows */  RETURN QUERY EXECUTE 'FETCH 5 FROM get_data_cur';   /* close cursor when we are done */  IF NOT FOUND THEN  EXECUTE 'CLOSE get_data_cur';  END IF; END;$;