CREATE PACKAGE
CREATE PACKAGE — создать пакет
Синтаксис
CREATE [ OR REPLACE ] PACKAGEимя_пакетаэлемент_пакета[ ... ]
Описание
CREATE PACKAGE создаёт новый пакет в текущей базе данных.
Пакет — это по сути схема, которая помогает организовать взаимосвязанные именованные объекты, поэтому его также можно создать командой CREATE SCHEMA, и с ним можно выполнять те же действия, что и с обычной схемой. Однако пакет может содержать только функции, процедуры и составные типы.
CREATE OR REPLACE PACKAGE либо создаст новый пакет, либо заменит существующее определение. Вы можете заменить существующий пакет, если он содержит только функции и типы, другие объекты должны быть предварительно удалены. Если при замене пакета не меняются сигнатуры содержащихся в нём функций, их содержимое заменяется, а зависимые объекты остаются. Если же сигнатура функции меняется, фактически создаётся отдельная функция. Новая функция будет создана успешно только при отсутствии объектов, зависящих от предыдущей, в противном случае CREATE OR REPLACE PACKAGE завершается ошибкой. То же ограничение действует при замене типов. При замене пакетов убедитесь, что никакие другие сеансы не используют их (другими словами, перед заменой пакетов остановите использующее их приложение).
Параметры
имя_пакетаИмя создаваемого пакета. Имя пакета должно отличаться от имени любого существующего пакета или схемы в текущей базе данных. Имя не может начинаться с
pg_, так как такие имена зарезервированы для системных схем.элемент_пакетаОператор SQL, определяющий объект, который будет создан в пакете. В настоящее время внутри
CREATE PACKAGEдопускаются только операторыCREATE FUNCTION,CREATE TYPEиCREATE PROCEDURE. Подкоманды обрабатываются по существу так же, как и отдельные команды, выполняемые после создания пакета. По умолчанию все переменные, объявленные в функции инициализации пакета, а также функции и процедуры пакета являются публичными, поэтому с помощью записи с точкой к ним могут обращаться функции, процедуры и анонимные блоки, импортирующие пакет. Модификатор#privateопределяет функции и процедуры как внутренние, а модификатор#exportопределяет, какие переменные пакета являются публичными. Более подробно функции и модификаторы пакетов описаны в Разделе 45.11.
Замечания
Чтобы создать пакет, пользователь должен быть суперпользователем или иметь право CREATE для текущей базы данных.
Примеры
Создание пакета counter с функциями:
CREATE PACKAGE counter
CREATE FUNCTION __init__() RETURNS void AS $$ -- инициализация пакета
#export on
DECLARE
n int := 1; -- публичная пакетная переменная n
k int := 3; -- публичная пакетная переменная k
BEGIN
FOR i IN 1..10 LOOP
n := n + n;
END LOOP;
END;
$$
CREATE FUNCTION inc() RETURNS int AS $$ -- публичная пакетная функция inc()
BEGIN
n := n + 1;
RETURN n;
END;
$$
;Заметьте, что отдельные подкоманды не заканчиваются точкой с запятой, так же как в CREATE SCHEMA, и при создании функций не указывается язык.
Если в функции инициализации пакета указан модификатор #export on, все объявленные переменные являются публичными, то есть они доступны снаружи пакета. Отсутствие в пакете модификатора #export (значение по умолчанию) приводит к тому же результату. Функция inc() по умолчанию является публичной и доступна снаружи пакета, как и любая другая функция или процедура пакета.
Следующий пример показывает как можно использовать описанный выше пакет.
DO $$
#import counter
BEGIN
RAISE NOTICE '%', counter.n;
RAISE NOTICE '%', counter.inc();
END;
$$;
NOTICE: 1024
NOTICE: 1025Другой вариант предыдущего примера:
CREATE PACKAGE foo
CREATE TYPE footype AS (a int, b int)
CREATE FUNCTION __init__() RETURNS void AS $$
#export y
DECLARE
x int := 1; -- внутренняя пакетная переменная x
y int := 5; -- публичная пакетная переменная y
BEGIN
RAISE NOTICE 'foo initialized';
END;
$$
CREATE FUNCTION get_x() RETURNS int AS $$ -- публичная пакетная функция get_x()
BEGIN
RETURN x;
END;
$$
CREATE PROCEDURE set_x(val int) AS $$ -- публичная пакетная процедура set_x()
BEGIN
x := val;
CALL foo.check_x();
END;
$$
CREATE PROCEDURE check_x() AS $$ -- внутренняя пакетная процедура check_x()
#private
BEGIN
IF x <= 0 THEN
RAISE INFO 'now x is not natural number';
ELSE
RAISE INFO 'now x is natural number';
END IF;
END;
$$
;В этом примере переменная y, функция get_x() и процедура set_x(int) из пакета foo являются публичными.
Другой вариант предыдущего примера:
DO $$ #import foo BEGIN RAISE INFO 'y = %', foo.y; RAISE INFO 'x = %', foo.get_x(); CALL foo.set_x(25); RAISE INFO 'x = %', foo.get_x(); END; $$; INFO: y = 5 INFO: x = 1 INFO: x set to natural value INFO: x = 25
Ниже показано, как можно добиться того же результата командой CREATE SCHEMA:
CREATE SCHEMA foo;
CREATE TYPE foo.footype AS (a int, b int);
CREATE FUNCTION foo.__init__() RETURNS void AS $$
#export y
DECLARE
x int := 1; -- внутренняя пакетная переменная x
y int := 5; -- публичная пакетная переменная y
BEGIN
RAISE NOTICE 'foo initialized';
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION foo.get_x() RETURNS int AS $$ -- публичная пакетная функция get_x()
#package
BEGIN
RETURN x;
END;
$$ LANGUAGE plpgsql;
CREATE PROCEDURE foo.set_x(val int) AS $$ -- публичная пакетная процедура set_x()
#package
BEGIN
x := val;
CALL foo.check_x();
END;
$$ LANGUAGE plpgsql;
CREATE PROCEDURE foo.check_x() AS $$ -- внутренняя пакетная процедура check_x()
#package
#private
BEGIN
IF x <= 0 THEN
RAISE INFO 'x set to not natural value';
ELSE
RAISE INFO 'x set to natural value';
END IF;
END;
$$ LANGUAGE plpgsql; Обратите внимание, что в этом случае вы должны использовать модификаторы #package.