Курсор postgresql: Postgres Pro Standard : Документация: 10: 40.7. Курсоры : Компания Postgres Professional

Как использовать курсор в функциях на PL/pgSQL? | Info-Comp.ru

И снова SQL! А если быть точнее PL/pgSQL, сегодня поговорим именно об этом расширение языка SQL, а конкретней о том, как использовать курсор при написании функции в СУБД PostgreSQL. И о том, для чего вообще нужны курсоры, и когда их лучше использовать.

Надеюсь, Вы не забыли все те примеры и уроки, которые мы рассматривали ранее, так как для прочтения этой статьи необходимы минимальные знания SQL, для того чтобы Вы вспомнили, вот эти материалы: Как написать функцию на PL/pgSQL, Написание табличной функции на PL/pgSQL — функция, которая возвращает таблицу в последней, кстати, уже затрагивалась тема курсоров, но не подробно, поэтому сегодня мы поговорим о курсорах уже подробней.

Что такое курсор в SQL?

Курсор в SQL – это временная выборка записей в процессе выполнения функции, над которой могут выполняться необходимые Вам действия, данная выборка является указателем на область памяти.

Курсоры могут быть очень полезны, например, если Вам в функции необходимо выполнять определенные действия с каким то набором строк, при этом до начала выполнения функции Вы даже не знаете, сколько строк будет при обработке той или иной записи. Если проще курсор — это просто запрос, который запускается в процессе выполнения функции.

Например, у Вас есть определенный запрос (набор записей), над каждой строкой которого необходимо выполнять какие то хитрые действия, которые нужно запомнить для операции над следующей строкой этого же запроса.

О том, что курсоры могут быть полезны, мы поговорили, но когда их лучше использовать? А использовать их лучше всего только тогда, когда у Вас нет другого выхода! Потому что курсор является очень ресурсоемким решением. В принципе если Вы будете выполнять операции над небольшим количеством записей, то это приемлемо, а если необходимо обработать большой объем данных, то Вы можете очень долго ждать, пока будет выполняться Ваша функция, а как Вы знаете быстрота в нашем деле чуть ли не главный фактор.

Пример использования курсора в функции на PL/pgSQL

О теории мы поговорили пора переходить к практике, и для начала общий синтаксис курсора в функции.

   
   CREATE OR REPLACE FUNCTION название функции(типы переменных)
    RETURNS тип возвращаемого значения  AS
  $BODY$
   DECLARE
        объявление переменных
        объявление курсора
   BEGIN
     открытие курсора
        перебор данных и операции над ними
     закрытие курсора
     RETURN возвращение значения;
   END;
   $BODY$
     LANGUAGE 'plpgsql' VOLATILE


Теперь давайте приведем рабочий пример использования курсора, т.е. напишем функцию, в которой мы будем использовать курсор.

Примечание! Данный пример не из жизни, он смоделирован мной, поэтому у Вас такой ситуации может и не возникнуть.

Для начала давайте определим, с какими данными мы будем работать, допустим, у нас есть таблица, в которой хранятся записи о сотрудниках, которые постоянно находятся в командировках, или просто у них есть служебный транспорт, да это и не важно, важно то, что им выделяют деньги на расходы, а они отчитываются по этим расходам.

Пример таблицы с несколькими записями:


id_perid_userrashodsummapr
111001000
121001100
21100900
22100900
311101000
3210010010

где,

  • id_per – период по которому идет отчет;
  • id_user – идентификатор сотрудника;
  • rashod – сумма расходов за этот период;
  • summa – сумма, которая выделялась на расходы;
  • pr – возможная премия, на погашение задолженности в прошлом периоде.

Стоит следующая задача, нам необходимо определить тот период у сотрудников, в котором они расходовали средств больше, чем им выдали, и потом не возместили. При условии, что в следующем месяце им могут возместить этот расход (колонка pr), а могут и не возместить.

Т.е. в нашем примере у сотрудника с id_user = 1, этот период будет с id_per = 2, а у сотрудника с id_user = 2, этот период будет с id_per = 3. Другими словами, во втором периоде они оба перерасходовали выданные им средства, но сотруднику с id_user = 2 в следующем месяце их возместили, а с id_user = 1 нет, поэтому первый период возникновения перерасхода (причем не погашенного) у сотрудника с id_user = 1 будет именно период с id_per = 2.

В общем как то так:). Но для нас главное научиться использовать курсор в функциях, и наша функция будет выглядеть вот так.

Схема в базе PostgreSQL называется test и таблица тоже называется test, а функцию я назвал test.my_fun(numeric). Numeric – это как Вы помните тип входящего параметра.

   
   CREATE OR REPLACE FUNCTION test.my_fun(numeric)
     RETURNS numeric  AS
   $BODY$
   DECLARE
        _id_user ALIAS FOR $1;
        --объявляем курсор
        crs_my CURSOR FOR select id_per, rashod, summa from test. test where 
                                                      id_user = _id_user order by id_per;
        --объявляем нужные нам переменные
        _id_per numeric;
        _rashod numeric;
        _summa numeric;
        _pr numeric;
        _var numeric;
        _rezult numeric;
   BEGIN
    _pr:=0;
    OPEN crs_my;--открываем курсор
    LOOP --начинаем цикл по курсору
    --извлекаем данные из строки и записываем их в переменные
    FETCH crs_my INTO _id_per, _rashod, _summa;
    --если такого периода и не возникнет, то мы выходим
    IF NOT FOUND THEN EXIT;END IF;
    --ищем сумму возмещения, если она была
    select into _pr pr from test.test where id_user=_id_user and id_per = _id_per+1;
    _var = _rashod - _summa;
        if _var > 0 then
                _var = _var - _pr;
        End if;
        _rezult=_id_per;
        --если _var даже после возмещения больше нуля, то выходим и возвращаем период
        EXIT when _var > 0;
     END LOOP;--заканчиваем цикл по курсору
     CLOSE crs_my; --закрываем курсор
    RETURN _rezult;--возвращаем результат
   END;
   $BODY$
     LANGUAGE 'plpgsql' VOLATILE


В функции я все прокомментировал, надеюсь понятно. Главное здесь это наш курсор crs_my, затем мы просто открываем его, извлекаем данные с помощью FETCH по каждой строке наших данных и делаем это с помощью цикла LOOP. Есть один нюанс, когда будете писать запрос для курсора, в Ваших функциях, то учитывайте сортировку, потому что цикл работает с первой строки записи, и если необходимо изменить порядок извлечения данных, то делайте это в запросе, который используется в курсоре.

Использовать функцию можно вот так:

   
   SELECT test.my_fun(1)


Результат, как Вы помните, будет 2.

Если хотите запустить по всем записям, то используйте вот такой запрос:

   
   SELECT test.my_fun(id_user) FROM test.test


Заметка! Для комплексного изучения языка SQL рекомендую почитать мою книгу «SQL код». Данный книга рассчитана на изучение языка SQL как стандарта, т.е. на изучение тех возможностей SQL, которые доступны и точно будут работать во всех популярных системах управления базами данных (СУБД).

Вот такой простой пример! Надеюсь, курсоры Вам как-то помогут в ваших функциях, но снова напомню, злоупотреблять курсорами не следует, а использовать их нужно только по необходимости. Удачи!

Python и базы данных | Модуль psycopg. Подключение к серверу PostgreSQL

Последнее обновление: 25.11.2022

Одной из наиболее популярных реляционных систем баз данных является PostgreSQL. Рассмотрим, как работать с базами данных PostgreSQL в приложении на языке Python.

Перед началом работы естественно должна быть установлена сама PostgreSQL. Про установку PostgreSQL можно прочитать в соответствующей статье
Установка сервера PostgreSQL.

Стандартные библиотеки Python не предоставляют встроенного функционала для работы с PostgreSQL, однако есть большое количество сторонних библиотек. Наиболее популярной из них
является Psycopg 2 (официальный сайт Psycopg). Данная библиотека реализована на языке C, благодаря чему обладает сравнительно большой производительностью.

Установка psycopg

Для установки выполним в терминале следующую команду:

pip install psycopg2

После этого мы можем импортировать библиотеку в программе на Python:

import psycopg2

Подключение к серверу PostgreSQL

Для подключения к серверу PostgreSQL применяется функция connect(). Она принимает настройки подключения:


psycopg2.connect(dbname="db_name", host="db_host", user="db_user", password="db_pass", port="db_port")

Функция принимает следующие параметры:

  • dbname: имя базы данных

  • user: имя пользователя

  • password: пароль пользователя

  • host: хост/адрес сервера

  • port: порт (если не указано, то используется порт по умолчанию — 5432)

При удачном подключении функция connect создает новую сессию базы данных и возвращает объект connection

Класс connection предоставляет ряд методов для работы с подключением к БД:

  • close(): закрывает подключение

  • cursor(): возвращает объект cursor для осуществления запросов к бд

  • commit(): поддверждает транзакцию

  • rollback(): откатывает транзакцию

Например, покдлючимся к стандартной базе данных «postgres» на локальном сервере PostgreSQL:


import psycopg2

conn = psycopg2. connect(dbname="postgres", user="postgres", password="123456", host="127.0.0.1", port="5432")
print("Подключение установлено")
conn.close()

В данном случае подключение идет для встроенного пользователя по умолчанию «postgres».

Курсор и операции с данными

Метод cursor() объекта connection возвращает курсор — объект cursor, через который можно отправлять запросы к базе данных. Для этого класс cursor предоставляет ряд методов:

  • execute(query, vars=None): выполняет одну SQL-инструкцию. Через второй параметр в код SQL можно передать набор параметров в виде списка или словаря

  • executemany(query, vars_list): выполняет параметризованное SQL-инструкцию. Через второй параметр принимает наборы значений, которые передаются в выполняемый код SQL.

  • callproc(procname[, parameters]): выполняет хранимую функцию. Через второй параметр можно передать набор параметров в виде списка или словаря

  • mogrify(operation[, parameters]): возвращает код запроса SQL после привязки параметров

  • fetchone(): возвращает следующую строку из полученного из БД набора строк в виде кортежа. Если строк в наборе нет, то возвращает None

  • fetchmany([size=cursor.arraysize]): возвращает набор строк в виде списка. количество возвращаемых строк передается через параметр.
    Если больше строк нет в наборе, то возвращается пустой список.

  • fetchall(): возвращает все (оставшиеся) строки в виде списка. При отсутствии строк возвращается пустой список.

  • scroll(value[, mode='relative']): перемещает курсор в наборе на позицию value в соответствии с режимом mode.

Определение курсора:


import psycopg2

conn = psycopg2.connect(dbname="postgres", user="postgres", password="123456", host="127.0.0.1")
cursor = conn.cursor()

cursor.close()  # закрываем курсор
conn.close()    # закрываем подключение

Закрытие подключения и курсора

Стоит отметить, что оба объекта — connection и cursor могут использоваться как менеджеры контекста. То есть с помощью выражения with
определить контекста. Однако если объект cursor по завершению закрывается, то объект connection НЕ закрывается:


import psycopg2

conn = psycopg2.connect(dbname="postgres", user="postgres", password="123456", host="127.0.0.1", port="5432")
with conn:
    with conn.cursor() as cursor:
        print("Подключение установлено")

print(cursor.closed)    # True - курсор закрыт
# cursor.close()  # нет смысла - объект cursor уже закрыт
conn.close()    # объект conn не закрыт, надо закрывать

Модель выполнения запросов

Перед выполнением первой команды SQL автоматически создается транзакция, в процессе которой можно выполнять различные выражения SQL с помощью методов execute/executemany курсора, но для
подтверждения их выполнения необходимо вызывать метод commit() объекта connection. Условно это может выглядеть так:


import psycopg2

conn = psycopg2. connect(dbname="postgres", user="postgres", password="123456", host="127.0.0.1")
cursor = conn.cursor()

cursor.execute(sql1)

conn.commit()   # реальное выполнение команд sql1

cursor.close()
conn.close()

Здесь реальное выполнение условной команды sql1 производится только при выполнении метода conn.commit().
Если же надо, чтобы выражения sql автоматически выполнялись при каждом вызове метода cursor.execute(), то можно установить автокоммит с помощью свойства connection.autocommit:


import psycopg2

conn = psycopg2.connect(dbname="postgres", user="postgres", password="123456", host="127.0.0.1")

conn.autocommit = True  # устанавливаем актокоммит

cursor = conn.cursor()
cursor.execute(sql1)    # непосредственное выполнение команды sql1

cursor.close()
conn.close()

НазадСодержаниеВперед

PostgreSQL: Документация: 15: DECLARE

DECLARE

DECLARE — определить курсор

Synopsis

DECLARE   name   [ BINARY ] [ ASENSITIVE | НЕЧУВСТВИТЕЛЬНЫЙ ] [ [ НЕТ ] ПРОКРУТКА ]
    КУРСОР [ {С | БЕЗ } HOLD ] FOR   запрос  
 

Описание

DECLARE позволяет пользователю создавать курсоры, которые можно использовать для одновременного извлечения небольшого количества строк из более крупного запроса. После создания курсора из него извлекаются строки с помощью ПОЛУЧИТЬ .

Примечание

На этой странице описывается использование курсоров на уровне команд SQL. Если вы пытаетесь использовать курсоры внутри функции PL/pgSQL, правила другие — см. раздел 43.7.

Параметры

имя

Имя создаваемого курсора.

ДВОИЧНЫЙ

Заставляет курсор возвращать данные в двоичном, а не в текстовом формате.

НЕЧУВСТВИТЕЛЬНЫЙ
НЕЧУВСТВИТЕЛЬНЫЙ

Чувствительность курсора определяет, видны ли в курсоре изменения данных, лежащих в основе курсора, сделанные в той же транзакции после объявления курсора. INSENSITIVE означает, что они не видны, ASENSITIVE означает, что поведение зависит от реализации. Третье поведение, SENSITIVE , означающее, что такие изменения видны в курсоре, недоступно в PostgreSQL. В PostgreSQL все курсоры нечувствительны; поэтому эти ключевые слова не действуют и принимаются только для совместимости со стандартом SQL.

Указание INSENSITIVE вместе с FOR UPDATE или FOR SHARE является ошибкой.

ПРОКРУТКА
БЕЗ ПРОКРУТКИ

SCROLL указывает, что курсор может использоваться для непоследовательного извлечения строк (например, в обратном порядке). В зависимости от сложности плана выполнения запроса указание SCROLL может привести к снижению производительности на время выполнения запроса. NO SCROLL указывает, что курсор нельзя использовать для непоследовательного извлечения строк. По умолчанию в некоторых случаях разрешена прокрутка; это не то же самое, что указать SCROLL . Подробнее см. в примечаниях ниже.

С УДЕРЖАНИЕМ
БЕЗ УДЕРЖАНИЯ

WITH HOLD указывает, что курсор может продолжать использоваться после успешной фиксации создавшей его транзакции. WITHOUT HOLD указывает, что курсор нельзя использовать вне транзакции, которая его создала. Если не указаны ни БЕЗ УДЕРЖАНИЯ , ни С УДЕРЖАНИЕМ , по умолчанию используется БЕЗ УДЕРЖАНИЯ .

запрос

Команда SELECT или VALUES , которая предоставляет строки, возвращаемые курсором.

Ключевые слова ASENSITIVE , BINARY , INSENSITIVE и SCROLL могут появляться в любом порядке.

Примечания

Обычные курсоры возвращают данные в текстовом формате, таком же, как SELECT . Параметр BINARY указывает, что курсор должен возвращать данные в двоичном формате. Это снижает усилия по преобразованию как для сервера, так и для клиента за счет дополнительных усилий программиста для работы с зависимыми от платформы форматами двоичных данных. Например, если запрос возвращает значение единицы из целочисленного столбца, вы получите строку из 1 с курсором по умолчанию, тогда как с двоичным курсором вы получите 4-байтовое поле, содержащее внутреннее представление значения (в порядке байтов от старшего).

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

Примечание

Когда клиентское приложение использует протокол «расширенного запроса» для выполнения команды FETCH , сообщение протокола Bind указывает, должны ли данные извлекаться в текстовом или двоичном формате. Этот выбор переопределяет способ определения курсора. Таким образом, концепция двоичного курсора как таковая устарела при использовании расширенного протокола запросов — любой курсор можно рассматривать как текстовый или двоичный.

Если не указано WITH HOLD , курсор, созданный этой командой, можно использовать только в рамках текущей транзакции. Таким образом, DECLARE без WITH HOLD бесполезна вне блока транзакции: курсор будет существовать только до завершения оператора. Поэтому PostgreSQL сообщает об ошибке, если такая команда используется вне блока транзакции. Используйте BEGIN и COMMIT (или ROLLBACK ) для определения блока транзакции.

Если указано WITH HOLD и транзакция, создавшая курсор, успешно зафиксирована, к курсору могут по-прежнему обращаться последующие транзакции в том же сеансе. (Но если создающая транзакция прервана, курсор удаляется.) Курсор, созданный с помощью WITH HOLD , закрывается, когда на него выдается явная команда CLOSE или сеанс завершается. В текущей реализации строки, представленные удерживаемым курсором, копируются во временный файл или область памяти, чтобы они оставались доступными для последующих транзакций.

WITH HOLD нельзя указывать, если запрос включает FOR UPDATE или FOR SHARE .

Опция SCROLL должна быть указана при определении курсора, который будет использоваться для выборки назад. Этого требует стандарт SQL. Однако для совместимости с более ранними версиями PostgreSQL разрешает выборку назад без SCROLL , если план запроса курсора достаточно прост и для его поддержки не требуются дополнительные накладные расходы. Однако разработчикам приложений рекомендуется не полагаться на использование обратной выборки из курсора, который не был создан с помощью 9.0010 СВИТОК . Если указано NO SCROLL , то обратная выборка запрещена в любом случае.

Обратная выборка также запрещена, если запрос включает FOR UPDATE или FOR SHARE ; поэтому SCROLL в этом случае можно не указывать.

Предупреждение

Прокручиваемые курсоры могут давать неожиданные результаты, если они вызывают какие-либо изменчивые функции (см. Раздел 38.7). Когда ранее выбранная строка выбирается повторно, функции могут выполняться повторно, что может привести к результатам, отличным от результатов, полученных в первый раз. Лучше указать NO SCROLL для запроса, включающего изменчивые функции. Если это нецелесообразно, одним из обходных путей является объявление курсора SCROLL WITH HOLD и фиксация транзакции перед чтением из нее каких-либо строк. Это заставит материализовать весь вывод курсора во временное хранилище, чтобы изменчивые функции выполнялись ровно один раз для каждой строки.

Если запрос курсора включает FOR UPDATE или FOR SHARE , то возвращаемые строки блокируются во время их первой выборки, так же, как и для обычных Команда SELECT с этими параметрами. Кроме того, возвращаемые строки будут самыми последними версиями. . Использование FOR UPDATE предотвращает изменение строк другими сеансами между моментом их выборки и временем их обновления. Без ДЛЯ ОБНОВЛЕНИЯ , последующая команда WHERE CURRENT OF не будет иметь никакого эффекта, если строка была изменена с момента создания курсора.

Другая причина использования FOR UPDATE заключается в том, что без него последующее WHERE CURRENT OF может завершиться ошибкой, если запрос курсора не соответствует правилам стандарта SQL для «просто обновляемости» (в частности, курсор должен ссылаться только на одну таблицу и не использовать группировку или ORDER BY ). Курсоры, которые нельзя просто обновить, могут работать, а могут и нет, в зависимости от деталей выбора плана; поэтому в худшем случае приложение может работать при тестировании, а затем дать сбой в производстве. Если ДЛЯ ОБНОВЛЕНИЯ указано, курсор гарантированно обновляемый.

Основная причина не использовать FOR UPDATE с WHERE CURRENT OF — если вам нужно, чтобы курсор можно было прокручивать, или чтобы он был изолирован от одновременных обновлений (то есть продолжал показывать старые данные). Если это требование, обратите внимание на приведенные выше предостережения.

Стандарт SQL предусматривает использование курсоров только во встроенном SQL. Сервер PostgreSQL не реализует оператор OPEN для курсоров; курсор считается открытым, когда он объявлен. Однако ECPG, встроенный препроцессор SQL для PostgreSQL, поддерживает стандартные соглашения о курсорах SQL, в том числе те, которые включают операторы DECLARE и OPEN .

Вы можете просмотреть все доступные курсоры, запросив системное представление pg_cursors .

Примеры

Чтобы объявить курсор:

ОБЪЯВИТЬ liahona КУРСОР ДЛЯ ВЫБОРА * ИЗ фильмов;
 

Дополнительные примеры использования курсора см. в разделе FETCH.

Совместимость

Стандарт SQL позволяет использовать курсоры только во встроенном SQL и в модулях. PostgreSQL позволяет использовать курсоры в интерактивном режиме.

В соответствии со стандартом SQL изменения, внесенные в нечувствительные курсоры операторами UPDATE . .. WHERE CURRENT OF и DELETE ... WHERE CURRENT OF , видны в том же самом курсоре. PostgreSQL обрабатывает эти операторы так же, как и все другие операторы изменения данных, поскольку они не видны в нечувствительных курсорах.

Двоичные курсоры являются расширением PostgreSQL.

См. также

ЗАКРЫТЬ, ВЫБРАТЬ, ПЕРЕМЕСТИТЬ

Руководство по курсорам PostgreSQL. Погружение в то, как курсоры работают в… | Элвин Янг

Погружение в работу курсоров в PostgreSQL.

Опубликовано в

·

4 мин чтения

·

3 августа 2021 г.

Курсор базы данных — это указатель, который позволяет пользователю перебирать результат запроса в порядке строк. Как правило, курсоры могут быть определены с различными свойствами: «только для чтения» или «обновляемый», «только вперед» и «прокручиваемый», а также «чувствительный» или «нечувствительный». Мы обсудим эти свойства применительно к PostgreSQL и их внутренней работе.

Курсор можно определить с помощью предложения DECLARE со следующим синтаксисом:

 DECLARE   имя   [BINARY] [ASENSITIVE | НЕЧУВСТВИТЕЛЬНЫЙ ] [ [ НЕТ ] ПРОКРУТКА ] 
КУРСОР [ { С | WITHOUT } HOLD ] FOR запрос

Сначала планировщик/оптимизатор анализирует запрос в дерево запросов. Затем исполнитель будет обрабатывать дерево запросов и постепенно возвращать результаты, как описано здесь.

Каждый раз, когда выдается команда FETCH , исполнитель один раз запускает верхний узел дерева запросов. Он будет рекурсивно запускать своих потомков, и, в конце концов, верхний узел вернет следующую строку результирующего набора. Этот процесс можно выполнять итеративно, пока результат запроса не будет исчерпан и верхний узел не вернет NULL. (Примечание. Этот процесс обрабатывается процедурой ExecutionRun() , определенной в «execMain.c» исходного файла.)0005

Если курсор открыт, а SQL-транзакция, в которой был открыт курсор
, вносит существенное изменение в SQL-данные, то
видно ли это изменение через этот курсор до его закрытия,
определяется следующим образом:

— Если курсор нечувствителен, то
существенные изменения не видны.
— Если курсор чувствителен, то заметны
существенные изменения.
— Если курсор нечувствительный, то видимость значащих 9Изменения 0054 зависят от реализации.

На момент написания этой статьи PostgreSQL поддерживает только нечувствительные курсоры. Это означает, что изменения исходной таблицы (таблиц), сделанные в рамках одной и той же транзакции, после объявления курсора не будут видны. Таким образом, указание ASENSITIVE или INSENSITIVE не имеет никакого эффекта.

Действительно, снимок таблицы (таблиц) будет создан при открытии курсора (т. е. при его объявлении). Во время Fetch портал курсора будет загружать снимок каждый раз перед вызовом исполнителя. Он вытолкнет снимок только после того, как исполнитель завершит обработку. (Примечание: это видно из SPI_cursor_open_internal() и PortalRunSelect() .)

Возможность обновления

Курсоры можно сделать обновляемыми, добавив FOR UPDATE или FOR SH ARE в конце запроса . Это даст оператору SELECT эксклюзивную или общую блокировку, соответственно, от других параллельных транзакций при обновлении/чтении строки. Они полезны, когда мы хотим обновить или удалить строки в исходной таблице (таблицах) с помощью курсора, используя {ОБНОВЛЕНИЕ | УДАЛИТЬ} … ГДЕ ТЕКУЩИЙ ИЗ .

Имейте в виду, что возможность обновления курсора немного отличается от стандарта SQL:2014. В PostgreSQL любое обновление/удаление исходных таблиц, даже нечувствительных курсоров с по , сделанное с использованием {UPDATE | DELETE} … WHERE CURRENT OF операторов, не будет отображаться в том же самом курсоре. Это связано с тем, что моментальный снимок был сделан, когда курсор был открыт, как описано выше, задолго до того, как изменения могли произойти.

Возможность прокрутки

Если курсор указан с помощью SCROLL , его можно использовать для извлечения строк как в прямом направлении (т. е. следующая строка), так и в обратном направлении (т. е. предыдущая строка).

Это означает, что исполнитель должен иметь возможность выбирать строки в обратном направлении. В зависимости от плана запроса может потребоваться присоединить узел Materialize к дереву запросов для поддержки обратной выборки. Узел Materialize будет хранить все извлеченные строки во временном хранилище, называемом tuplestore, что позволяет снова получить доступ к предыдущим строкам в более позднее время.

Хранилище кортежей сохранит выбранные строки в массиве в памяти, если их общий размер меньше указанного значения. В противном случае он сохранит строки во временном файле на диске. Помимо включения обратной выборки, он также обеспечивал эффективный произвольный доступ к результату запроса, поскольку исключал необходимость для исполнителя сканировать большое количество строк, чтобы найти нужную строку.

Если указано WITH HOLD , на курсор можно будет продолжать ссылаться и использовать его после того, как транзакция, которая его создала, успешно зафиксирована. Во время объявления удерживаемого курсора запрос будет выполнен до завершения, а строки будут сброшены в хранилище кортежей. Каждый раз 9Команда 0010 FETCH выдается при следующей транзакции, вместо этого она извлекает строку из хранилища кортежей.

Внутренне новый портал создается всякий раз, когда курсор открывается с помощью DECLARE . Портал — это просто абстракция над состоянием выполнения курсора, и он будет использовать различные стратегии выполнения в зависимости от запроса . Вот некоторые важные из них:

  1. Если запрос содержит один оператор SELECT , будет запущен исполнитель, и каждый раз при выполнении будет возвращаться новая строка.0010 Выдается команда FETCH .
  2. Если запрос содержит один запрос INSERT / UPDATE / DELETE с предложением RETURNING , исполнитель выполнит обновление/вставку/удаление до завершения и выгрузит результат запроса в магазин кортежей.