Как создать временную функцию в PostgreSQL? - PullRequest
57 голосов
/ 14 февраля 2011

Я должен выполнить цикл в базе данных. Это только одноразовое требование. После выполнения функции я сейчас ее сбрасываю.

Есть ли хороший подход для создания временных / одноразовых функций?

Ответы [ 4 ]

90 голосов
/ 02 апреля 2012

Мне нужно было знать, как многократно использовать сценарий, который я писал.Оказывается, вы можете создать временную функцию, используя схему pg_temp.Это схема, которая создается по требованию для вашего соединения и где хранятся временные таблицы.Когда ваше соединение закрыто или истекает, эта схема удаляется.Оказывается, если вы создадите функцию на этой схеме, схема будет создана автоматически.Следовательно,

create function pg_temp.testfunc() returns text as 
$$ select 'hello'::text $$ language sql;

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

45 голосов
/ 28 июня 2015

Пара дополнительных примечаний к умному трюку в ответе @ crowmagnumb :

  • Функция должна быть с учетом схемы всегда, даже если pg_temp находится в search_path (как по умолчанию), в соответствии с Томом Лейном для предотвращения троянских коней:
CREATE FUNCTION <b>pg_temp.</b>f_inc(int)
  RETURNS int AS 'SELECT $1 + 1' LANGUAGE sql IMMUTABLE;

SELECT <b>pg_temp.</b>f_inc(42);
f_inc
-----
43
  • Функция, созданная во временной схеме, видна только внутри того же сеанса (как и временные таблицы).Это невидимо для всех других сессий (даже для той же роли).Вы можете получить доступ к функции в качестве другой роли в том же сеансе после SET ROLE.

  • Вы даже можете создать функциональный индекс на основе этой "временной" функции:

    CREATE INDEX foo_idx ON tbl (pg_temp.f_inc(id));
    

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


Если вам просто нужно многократно выполнять функцию и все, что вам нужно, это SQL, рассмотрите подготовленное заявление вместо.Он действует так же, как временная функция SQL , которая умирает в конце сеанса.Однако, не то же самое , и может использоваться только с EXECUTE, не вложенным в другой запрос.Пример:

PREPARE upd_tbl AS
UPDATE tbl t SET set_name = $2 WHERE tbl_id = $1;

Вызов:

EXECUTE upd_tbl(123, 'foo_name');

Подробности:

27 голосов
/ 14 февраля 2011

Если вы используете версию 9.0, вы можете сделать это с помощью новой инструкции DO:

http://www.postgresql.org/docs/current/static/sql-do.html

В предыдущих версиях вам нужно создать функцию, вызвать ее и снова отбросить.

0 голосов
/ 14 февраля 2011

Для рекламных процедур курсоры не так уж плохи. Однако они слишком неэффективны для использования в продуктах.

Они позволят вам легко зацикливаться на результатах SQL в БД.

...