Статьи

Хранимые функции как хранимые процедуры в PostgreSQL PL / pgSQL

PostgreSQL не поддерживает хранимые процедуры в том смысле, что база данных, как Oracle , но поддерживает хранимые функции . В этой статье я расскажу о некоторых тактиках, которые позволяют использовать хранимую функцию в PostgreSQL (хранимая функция и код ее вызова, написанный на PL / pgSQL ) как использование хранимой процедуры . Эти простые подходы позволяют разработчикам использовать хранимые функции PostgreSQL способом, более совместимым с использованием хранимых процедур.

Хранимые процедуры и хранимые функции очень похожи, и, на самом деле, я часто слышал термин «хранимая процедура», используемый взаимозаменяемо для хранимых процедур и для хранимых функций. Для целей этого поста существенные различия между ними можно суммировать как:

  1. Функции создаются с помощью ключевого слова FUNCTION, а процедуры — с помощью ключевого слова PROCEDURE.
  2. Хранимые процедуры не возвращают значение, но хранимые функции возвращают одно значение.

    • Возвращаемое значение хранимой функции можно использовать в инструкциях SELECT.

Поскольку PostgreSQL PL / pgSQL поддерживает только хранимые функции, определенные функции должны объявлять тип возвращаемого значения. К счастью, в случае нашей эмулированной « хранимой процедуры » мы можем объявить void в качестве возвращаемого типа . Это продемонстрировано в листинге кода ниже для реализации «Hello World», написанной на PL / pgSQL.

CREATE OR REPLACE FUNCTION helloWorld(name text) RETURNS void AS $helloWorld$
DECLARE
BEGIN
    RAISE LOG 'Hello, %', name;
END;
$helloWorld$ LANGUAGE plpgsql;

С помощью хранимой функции PostgreSQL с записанным типом возвращаемого значения void теперь мы можем вызвать ее из клиента. В этом случае я рассмотрю три подхода для вызова хранимой функции из другого кода PL / pgSQL.

PL / pgSQL: вызывать функцию через оператор SELECT

Одним из подходов для вызова хранимой функции в коде PL / pgSQL является использование SELECT INTO . Наиболее очевидным недостатком является то, что в случае процедуроподобной функции, возвращающей void, ничего полезного не выбирается, и поэтому выбираемая переменная должна игнорироваться в любом случае. Следующий листинг кода демонстрирует использование SELECT INTO для вызова процедуроподобной функции. Переменная в этом примере, называемая «dumped», не будет иметь ничего полезного, но этот оператор успешно вызывает хранимую функцию. Помимо показанной здесь строки, мне также нужна строка в разделе DECLARE для объявления переменной «dumped».

    SELECT INTO dumped helloWorld('Dustin');  

PL / pgSQL: вызов функции через присвоение переменной

Оператор присваивания PL / pgSQL обеспечивает еще один способ вызова хранимой функции, подобной процедуре. Как и в предыдущем примере, этот подход требует, чтобы переменная («игнорируемая») была объявлена ​​в разделе DECLARE, а затем этой переменной был присвоен результат функции, которая возвращает void, что также делает ее переменной одноразовой.

    ignored := helloWorld('Dustin');  

PL / pgSQL: используйте PERFORM для явного игнорирования возвращаемого значения

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

    PERFORM helloWorld('Dustin');  

Заключение

Хотя PostgreSQL поддерживает только хранимые «функции» (а не хранимые «процедуры»), он предоставляет синтаксис, позволяющий функциям приобретать свойства, подобные процедурам. Позволяя хранимым функциям возвращать void и вызываться из кода PL / pgSQL через PERFORM, который не ожидает значения результата, PostgreSQL позволяет клиентскому коду выглядеть так, как будто он вызывает хранимую процедуру, а не хранимую функцию.