it-swarm-ru.tech

Как создать временную функцию в PostgreSQL?

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

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

55
Anand

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

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

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

88
crowmagnumb

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

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

SELECT pg_temp.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');

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

44
Erwin Brandstetter

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

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

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

27
a_horse_with_no_name