Як створити тимчасову функцію в PostgreSQL?


82

Мені потрібно виконати цикл у базі даних. Це лише одноразова вимога. Після виконання функції я кидаю функцію зараз.

Чи існує хороший підхід для створення тимчасових / одноразових функцій?

Відповіді:


115

Мені потрібно було знати, як багато разів використовувати сценарій, який я писав. Виявляється, ви можете створити тимчасову функцію, використовуючи схему pg_temp. Це схема, яка створюється на вимогу для вашого з’єднання і там зберігаються тимчасові таблиці. Коли ваше з’єднання закрите або закінчується, ця схема відпадає. Виявляється, якщо ви створюєте функцію на цій схемі, схема буде створена автоматично. Отже,

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

буде функцією, яка буде триматися до тих пір, поки триває зв’язок. Не потрібно викликати команду скидання.


61

Кілька додаткових приміток до розумного трюку у відповіді @ 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.

  • Ви навіть можете створити функціональний індекс на основі цієї функції "temp":

    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');

Подробиці:


30

Якщо ви використовуєте версію 9.0, ви можете зробити це за допомогою нового оператора DO:

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

У попередніх версіях вам потрібно буде створити функцію, викликати її та знову скинути.


4
... Це корисно для написання сценаріїв на терміналі, але ви не можете викликати його знову, як "анонімна функція" (або лямбда), тому статистика DO не настільки корисна, як "тимчасова функція".
Пітер Краус

@PeterKrauss: якщо ви хочете зателефонувати йому знову, вам потрібно створити реальну функцію.
a_horse_with_no_name

Звичайно, мій a_hourse :-) Я показував лише теоретичний шлях до реалізації "тимчасового" ... Ось чому краща відповідь (можлива з PostgreSQL), на основне питання, така pg_temp.foo(). Я не розумію, чому (!?) Сьогодні, 2014 року, з такими простими і такими швидкими прикладами, як Lua , мови SQL DML не можуть пропонувати лямбда-функції (!).
Пітер Краус

7
Крім того, DOоператори не можуть мати вхідні параметри і не можуть повертати результат, на відміну від функцій.
Даніель Верите

2
Якщо він не повертається, чи слід називати це "функцією"?
AndreKR

-4

Для ad hock процедур, курсорів не надто погані. Однак вони занадто неефективні для використання продукту.

Вони дозволять вам легко прокручувати результати sql в базі даних.


6
Чому, на вашу думку, курсори неефективні в PostgreSQL?
Frank Heikens

2
Курсори утримують підключення до бази даних при циклі. Веб-сторінка з сотнями давно запущених курсорів погіршить зв’язки і поставить сайт / базу даних на коліна.
Байрон Уітлок,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.