Пусть есть процедура возвращающая курсор через INOUT параметр:
drop function p_return_cursor(inout refcur refcursor);
create or replace function p_return_cursor(inout refcur refcursor)
returns refcursor -- тут именно refcursor, т.к. он есть в параметрах с типом OUT
LANGUAGE plpgsql
as $$
begin
open refcur for select generate_series(1,10,1) as ID;
end
$$
Как в postgres в SQL вызвать её и получить набор данных.
1)
select p_return_cursor('refcur');
результат - '-- refcursor' ничего!
Произошёл вызов процедуры, был открыт курсор, далее курсор был вернут вызывающей среде (ссылка на курсор - указатель на первую запись) и тут же выполнен autocommit - при этом курсор сразу закрылся и более не существует. Поэтому в вызывающей среде мы ни чего не имеем.
Комментарий:
Important Note: The cursor remains open until the end of transaction, and since PostgreSQL works in auto-commit mode by default, the cursor is closed immediately after the procedure call, so it is not available to the caller.
To work with cursors you have to start a transaction (turn auto-commit off).
Для явного старта транзакции можно использовать BEGIN;
BEGIN initiates a transaction block, that is, all statements after a BEGIN command will be executed in a single transaction until an explicit COMMIT or ROLLBACK is given.
By default (without BEGIN), PostgreSQL executes transactions in "autocommit" mode, that is, each statement is executed in its own transaction and a commit is implicitly performed at the end of the statement (if execution was successful, otherwise a rollback is done).
Поэтому:
1)
begin;
select p_return_cursor('refcur');
и дальше мы находимся в запущенной транзакции, Postgres ждёт от нас explicit COMMIT or ROLLBACK. :) Тут можно посидеть, подумать, а нужны ли нам данные и если до, то можно извлечь их из открытого курсора.
fetch all in refcur;
1
2
3
4
5
6
7
8
9
10
Тут же выполняем повторно и уже ни чего не получаем, но не генерируется и ошибка, т.к. просто указать курсора находится в конце.
Можно передвинуть его на первую запись и опять выполнить извлечение.
MOVE first from refcur;
fetch all in refcur;
2
3
4
5
6
7
8
9
10
Почему с 2, а не с 1 пока для меня загадка!
Так же явно начать транзакцию можно так:
START TRANSACTION ISOLATION LEVEL READ COMMITTED READ only;
select p_return_cursor('refcur');
fetch all in refcur;
drop function p_return_cursor(inout refcur refcursor);
create or replace function p_return_cursor(inout refcur refcursor)
returns refcursor -- тут именно refcursor, т.к. он есть в параметрах с типом OUT
LANGUAGE plpgsql
as $$
begin
open refcur for select generate_series(1,10,1) as ID;
end
$$
Как в postgres в SQL вызвать её и получить набор данных.
1)
select p_return_cursor('refcur');
результат - '-- refcursor' ничего!
Произошёл вызов процедуры, был открыт курсор, далее курсор был вернут вызывающей среде (ссылка на курсор - указатель на первую запись) и тут же выполнен autocommit - при этом курсор сразу закрылся и более не существует. Поэтому в вызывающей среде мы ни чего не имеем.
Комментарий:
Important Note: The cursor remains open until the end of transaction, and since PostgreSQL works in auto-commit mode by default, the cursor is closed immediately after the procedure call, so it is not available to the caller.
To work with cursors you have to start a transaction (turn auto-commit off).
Для явного старта транзакции можно использовать BEGIN;
BEGIN initiates a transaction block, that is, all statements after a BEGIN command will be executed in a single transaction until an explicit COMMIT or ROLLBACK is given.
By default (without BEGIN), PostgreSQL executes transactions in "autocommit" mode, that is, each statement is executed in its own transaction and a commit is implicitly performed at the end of the statement (if execution was successful, otherwise a rollback is done).
Поэтому:
1)
begin;
select p_return_cursor('refcur');
и дальше мы находимся в запущенной транзакции, Postgres ждёт от нас explicit COMMIT or ROLLBACK. :) Тут можно посидеть, подумать, а нужны ли нам данные и если до, то можно извлечь их из открытого курсора.
fetch all in refcur;
1
2
3
4
5
6
7
8
9
10
Тут же выполняем повторно и уже ни чего не получаем, но не генерируется и ошибка, т.к. просто указать курсора находится в конце.
Можно передвинуть его на первую запись и опять выполнить извлечение.
MOVE first from refcur;
fetch all in refcur;
2
3
4
5
6
7
8
9
10
Почему с 2, а не с 1 пока для меня загадка!
Так же явно начать транзакцию можно так:
START TRANSACTION ISOLATION LEVEL READ COMMITTED READ only;
select p_return_cursor('refcur');
fetch all in refcur;