Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

  • Эта функция должна быть всегда квалифицирована на схеме, даже если pg_temp находится в пути search_path (например, по умолчанию), согласно Tom Lane для предотвращения троянских коней:
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.

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

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

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


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

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

Вызов:

EXECUTE upd_tbl(123, 'foo_name');

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

Ответ 3

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

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

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

Ответ 4

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

Они позволят вам легко зацикливать на sql-результаты в db.