Перейти к содержимому

Postgresql пакеты как в oracle

  • автор:

What's the equivalent to Oracle Packages in PostgreSQL

I’m pretty new to PostgreSQL and I wonder if such a thing exists.

I saw some discussions, but nothing concrete..

lospejos's user avatar

3 Answers 3

No, there is no equivalent.

The only remotely similar thing would be to create one schema for each «package» and put all functions of one package into that schema. That way you have at least something like the namespace that packages give you.

This of course does not give you package private functions or package wide variables at all.

Postgresql пакеты как в oracle

Подскажите пожалуйтса, есть ли возможность создать пакеты или какой либо аналог как в oracle?

  • Войдите или зарегистрируйтесь, чтобы добавлять комментарии

Быть администратором

Быть администратором PostgreSQL не означает автоматически быть таковым в Oracle и вообще знание последнего.
Поэтому рассказывайте в подробностях, что такое пакет и с чем его едят

  • Войдите или зарегистрируйтесь, чтобы добавлять комментарии

Аналогов PL/SQL пакета в

Аналогов PL/SQL пакета в PostgreSQL нет.
Документация рекомендует для группировки функций использовать отдельные схемы.
Вместо пакетных переменных можно использовать временные таблицы.

Postgresql пакеты как в oracle

В Postgres Pro реализованы пакеты, подобные пакетам в Oracle . Они могут быть полезны при портировании с PL/SQL на PL/pgSQL . В этом разделе описаны различия между пакетами в Postgres Pro и Oracle.

В Oracle пакет — это объект, представляющий собой схему, которая группирует логически связанные типы, глобальные переменные и подпрограммы (процедуры и функции). Пакет состоит из спецификации и тела (хотя, в общем случае тело пакета может отсутствовать). В спецификации пакета объявляются элементы, на которые можно ссылаться вне пакета и использовать в приложениях: типы, переменные, константы, исключения, курсоры и подпрограммы. Тело пакета включает в себя реализацию подпрограмм пакета, объявление внутренних переменных, а также секцию инициализации. Переменные, типы и подпрограммы, объявленные в теле пакета, недоступны вне пакета.

Ниже приведён пример спецификации пакета counter на PL/SQL в Oracle , содержащего глобальную переменную n и функцию inc :

В теле пакета counter в Oracle объявлены функция inc и глобальная переменная k (доступна только в теле пакета).

Глобальные переменные пакета существуют в течение сеанса. Обратите внимание, что в теле пакета была определена секция инициализации — блок кода, который выполняется один раз за сеанс при первом обращении к любому элементу пакета. В Oracle к элементам пакета можно обращаться, используя запись с точкой: имя_пакета . элемент_пакета .

В Postgres Pro пакет по сути представляет собой схему, содержащую функцию инициализации и не содержащую ничего, кроме функций, процедур и составных типов. Функция инициализации — это функция на PL/pgSQL с именем __init__ , которая не имеет аргументов и возвращает значение типа void . Функция инициализации должна быть определена до любой другой функции пакета. Все переменные, объявленные в функции инициализации, являются глобальными и публичными, то есть функции других пакетов могут обращаться к ним, используя запись с точкой. Например, на переменную bar , объявленную в функции __init__ пакета foo , можно ссылаться как foo.bar .

Переменные пакета доступны только из кода на языке PL/pgSQL . Для получения значений глобальных переменных пакета из SQL-запроса ( SELECT ) или DML-оператора ( INSERT , UPDATE , DELETE ), необходимо создать функцию-геттер, возвращающую значение глобальной переменной. Для определения переменных пакета, объявленных как константы, используется стандартный для PL/pgSQL синтаксис. Функция инициализации пакета вызывается автоматически при первом обращении к любому из следующих элементов в текущем сеансе:

  • Любая функция данного пакета с модификатором #package
  • Блок кода (анонимный или функция), импортирующий данный пакет

Функцию инициализации можно вызвать вручную, чтобы сбросить значения переменных пакета. Для этого также можно использовать встроенную функцию plpgsql_reset_packages() , но она сбрасывает значения глобальных переменных всех пакетов в текущем сеансе (аналог DBMS_SESSION.RESET_PACKAGES в Oracle ).

Описанный выше пример пакета counter в Oracle после портирования в Postgres Pro примет следующий вид:

Использовать этот пакет в Postgres Pro можно так:

Стоит отметить следующее.

Пакет не может содержаться в схеме, так как сам является схемой.

Имя пакета должно отличаться от имени любого уже существующего пакета или схемы в текущей базе данных.

Пакет может содержать только составные типы, глобальные переменные, процедуры и функции (например, создание таблиц, представлений, последовательностей в пакетах не поддерживается).

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

Как функции пакета, так и импортирующие его блоки кода должны быть написаны на языке PL/pgSQL .

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

Глобальные переменные пакета могут инициализироваться как при объявлении:

так и позже в теле функции инициализации __init__ . Для внешнего кода, использующего пакет, эти варианты эквивалентны.

Типы должны быть объявлены в начале пакета, до определения первой подпрограммы.

Для поддержки пакетов Postgres Pro включает следующие усовершенствования:

Поддержка пакетов в стиле Oracle в СУБД Postgres Pro 15 Enterprise

В новой версии своего флагманского дистрибутива Postgres Pro 15 Enterpise, компания Postgres Pro добавила поддержку функциональности пакетов: расширен синтаксис PL/pgSQL и добавлены новые механизмы в среду выполнения хранимых процедур.

В данной статье описана поддержка функциональности пакетов в Postgres Pro 15 Enterpise:

группировка типов переменных процедур и функций в пакет;

поддержка секции инициализации пакетов;

поддержка глобальных переменных пакета доступных в течении всей «жизни» сессии.

Также в статье будут рассмотрены особенности использования пакетов в СУБД Postgres Pro Enterprise.

Введение

Один из самых трудоемких этапов в проекте миграции с СУБД Oracle на PostgreSQL является миграция хранимого кода Oracle PL/SQL на PL/pgSQL. Это связано с отсутствием поддержки пакетов (packages) в PL/pgSQL. Данное обстоятельство приводит к необходимости переписывания кода, – простой конвертацией синтаксических конструкций уже не обойтись.

Для решения вышеописанной проблемы, то есть для упрощения миграции с Oracle, в СУБД Postgres Pro 15 Enterprise была добавлена поддержка функциональности пакетов (packages) «в стиле Oracle». Необходимо отметить, что пакеты в Postgres Pro 15 Enterprise не обеспечивают полную поддержку синтаксиcа Oracle PL/SQL, то есть ручная доработка кода при миграции все равно потребуется. Тем не менее, поддержка функциональности пакетов позволяет в разы уменьшить затраты на изменение кода при миграции.

С технической точки зрения, поддержка пакетов в PostgreSQL, представляет собой расширение синтаксиса языка PL/pgSQL (с небольшими дополнениями в ядре СУБД), благодаря которому реализуется функциональный аналог пакетов Oracle и вводится ряд дополнительных команд для работы с ними.

Что такое пакет в СУБД Oracle

Прежде чем перейти к описанию функциональности пакетов в СУБД Postgres Pro 15 Enterprise, кратко напомним, что такое пакет в СУБД Oracle.

Пакет Oracle PL/SQL – это объект схемы, который группирует логически связанные типы, курсоры, константы, исключения, глобальные переменные и подпрограммы (процедуры и функции) в единое целое.

Пакет состоит из двух частей, спецификации пакета и тела пакета, хотя в общем случае, тело пакета может отсутствовать.

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

Тело пакета включает в себя реализацию подпрограмм пакета, объявление внутренних переменных, а также секцию инициализации. Переменные и типы, а также подпрограммы, объявленные в теле пакета, недоступны для использования вне пакета.

Рис. 1 Пакет в СУБД Oracle Database

Ниже приведен пример спецификации PL/SQL-пакета counter в СУБД Oracle, содержащего глобальную переменную n и функцию inc:

В теле пакета counter в СУБД Oracle присутствует объявление приватной глобальной переменной k (доступна только в теле пакета) и реализация функции inc:

Глобальные переменные пакета существуют в течении всего времени «жизни» сессии. Также, обратим внимание на то, что в теле пакета была определена секция инициализации – блок кода, который выполняется только один раз в сессии, при первом обращении к любому элементу пакета.

При обращении к любому элементу пакета, в СУБД Oracle, указывается его имя и название элемента пакета, через разделитель точка «.»:

Поддержка функциональности пакетов в Postgres Pro 15 Enterprise

Для реализации функциональности пакетов СУБД Oracle были добавлены новые команды, а также дополнительные директивы (прагмы) интерпретатора PL/pgSQL.

Следует отметить, что это именно реализация основной функциональности пакетов, а не полное копирование синтаксиса и логики из СУБД Oracle. Главное назначение этой новой возможности – упрощение миграции кода Oracle PL/SQL при переходе в PL/pgSQL Postgres Pro.

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

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

Соглашения о пакетах в Postgres Pro Enterprise

Определение пакета:

Пакетом считается схема, содержащая функцию инициализации и не содержащая ничего, кроме функций, процедур и композитных типов.

Функцией инициализации пакета (init-функцией) называется содержащаяся в соответствующей схеме функция на языке PL/pgSQL с именем __init__, не имеющая параметров и возвращающая тип void.

Глобальными переменными пакета являются переменные, объявленные в функции инициализации.

Таким образом, переменные, определенные в блоке declare функции инициализации пакета, считаются пакетными и доступны для обращения из других функций пакета по имени, а извне его – при импортировании (см. раздел «Новые синтаксические элементы») – через квалифицированные имена (с указанием имени пакета через точку). Например: переменная bar, определенная в declare-блоке init-функции пакета foo, доступна извне пакета как foo.bar.

Рис. 2 Пакет в СУБД Postgres Pro Enterprise 15

Отдельно стоит обратить внимание на то, что пакетные переменные доступны только из кода на языке PL/pgSQL. В хранимых процедурах, разработанных на других языках, например на PL/Perl, PL/V8 – они недоступны. Для получения значений глобальных переменных пакета из SQL-запроса (оператор SELECT) или DML-оператора (INSERT, UPDATE, DELETE) в пакет необходимо добавить функцию, которая должна возвращать значение глобальной переменной. Подобное поведение аналогично СУБД Oracle – в ней точно также глобальные переменные пакетов недоступны в SQL-запросах. Например:

Пакетные переменные могут быть константами – синтаксис определения и поведение таких констант стандартны для PL/pgSQL.

Функция инициализации пакета вызывается автоматически при первом (в текущей сессии) обращении к какой-либо его функции или процедуре, имеющей статус пакетной (см. раздел «Новые синтаксические элементы»), к любой глобальной переменной пакета, или же при выполнении любого блока кода (анонимному, процедуры или функции) импортирующего данный пакет. Ручной вызов функции инициализации не требуется, но при желании может быть выполнен, что приведет к сбросу значений пакетных переменных. Также предусмотрена специальная функция plpgsql_reset_packages() для сброса глобальных переменных всех пакетов в текущей сессии – аналог процедуры DBMS_SESSION.RESET_PACKAGES в СУБД Oracle.

Вышеописанный пример пакета counter в СУБД Oracle, при его портировании в СУБД Postgres Pro Enterprise, примет следующий вид (синтаксис оператора создания пакета аналогичен как в СУБД Oracle):

Использование этого пакета в СУБД Postgres Pro Enterprise будет выглядеть следующим образом:

Отдельно отметим нюансы использования пакетов:

Пакет не может содержаться в схеме, т.к. сам является схемой.

Пакет не может иметь одинаковое имя с какой-либо еще схемой.

Пакет может содержать только типы, глобальные переменные, константы, курсоры, процедуры и функции. НЕ поддерживается cоздание таблиц, представлений и последовательностей в пакете-схеме. Это ограничение точно также есть и в СУБД Oracle — невозможно в пакете PL/SQL вставить операто создания таблицы (CREATE TABLE), представления (CREATE VIEW), последовательности (CREATE SEQUENCE) и т.д.

Все элементы пакета являются публичными, то есть все элементы пакета доступны из любого импортировавшего пакет блока кода. Спецификация и тело пакета отдельно НЕ определяются.

Как функции пакета, так и импортирующие его блоки кода должны быть написаны на языке PL/pgSQL.

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

Инициализация глобальной переменной пакета может производиться как при ее объявлении (declare x int := 42;), так и позже – в теле функции инициализации __init__(). Для использующего пакет внешнего кода эти варианты эквивалентны.

Объявления типов в пакете должны располагаться в начале пакета, до определения первой функции или процедуры пакета.

Функция инициализации пакета должна быть первой подпрограммой, определенной в пакете.

Новые синтаксические элементы

Для поддержки функциональности пакетов, в СУБД Postgres Pro Enterprise были добавлены следующие нестандартные синтаксические элементы:

Модификаторы (прагмы функций). Прагма – это директива интерпретатора PL/pgSQL

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *