# Занятие 04: Установка и сопровождение / Миграция

> Исходная страница в нативном Markdown: Установка и сопровождение / Миграция

---

Индекс LLMS: [llms.txt](/ru/llms.txt)

---

<!-- Generated by scripts/generate_skeleton.py. -->

> [!NOTE]
> Эта страница извлечена из официального PDF в нативный Markdown. Текст слайдов, код и комментарии сохранены в порядке чтения; исходные PDF и HTML остаются эталоном макета.
> **HTML source:** [pgpro_04_migration.html](https://edu.postgrespro.ru/16/pgpro-16/pgpro_04_migration.html)
> **Archive:** [PGPRO-handouts-16.zip](https://edu.postgrespro.ru/16/PGPRO-handouts-16.zip)
> **Страниц PDF:** 22

## Page 1: Установка и сопровождение / Миграция {#source-page-001}

### Авторские права

© Postgres Professional, 2023–2026 Авторы: Алексей Береснев, Илья Баштанов, Павел Толмачев, Игорь Гнатюк Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)
### Использование материалов курса

Некоммерческое использование материалов курса (презентации, демонстрации) разрешается без ограничений. Коммерческое использование возможно только с письменного разрешения компании Postgres Professional. Запрещается внесение изменений в материалы курса.
### Обратная связь

Отзывы, замечания и предложения направляйте по адресу: edu@postgrespro.ru
### Отказ от ответственности

Компания Postgres Professional не несет никакой ответственности за любые повреждения и убытки, включая потерю дохода, нанесенные прямым или непрямым, специальным или случайным использованием материалов курса. Компания Postgres Professional не предоставляет каких-либо гарантий на материалы курса. Материалы курса предоставляются на основе принципа «как есть» и компания Postgres Professional не обязана предоставлять сопровождение, поддержку, обновления, расширения и изменения.

## Page 2: Темы {#source-page-002}

- Варианты и сложности миграции
- Миграция данных
- Миграция объектов бизнес-логики
- Реализация системных пакетов из Oracle
- Пакеты в Postgres Pro Enterprise
- Утилита ora2pgpro

## Page 3: Варианты и сложности {#source-page-003}

**Миграция на Postgres Pro Enterprise с других СУБД**
  - Oracle
  - MS SQL Server
  - MySQL
  - PostgreSQL
- Задачи и сложности
  - перенос схемы и данных: различия в типах, время переноса больших
  - объемов
  - перенос кода: хранимый код может сильно зависеть от СУБД
  - перенос нестандартного функционала

### Комментарии преподавателя

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

● несоответствие типов переносимых данных в исходной и целевой СУБД;

● время переноса серьезных объемов данных может оказаться достаточно большим;

● трудоемкость переноса хранимого кода, в том числе из-за различий языков и их диалектов;

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

Применительно к предмету курса, одним из популярных вариантов является миграция из Oracle в Postgres Pro Enterprise. Рассмотрению этой задачи посвящена почти вся эта тема.

<https://postgrespro.ru/docs/enterprise/16/pgpro-migration-tools>

## Page 4: Миграция объектов {#source-page-004}

**Объекты SQL**
  - таблицы, индексы, представления, последовательности
  - схемы
- Подпрограммы
  - процедуры, функции, триггеры
- Другие объекты и нестандартный функционал
  - пакеты
  - автономные транзакции

### Комментарии преподавателя

Миграция стандартных объектов SQL, таких как таблицы, индексы, представления и последовательности, относительно проста и поддается автоматизации.

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

Миграция других объектов — тоже сложная задача, поскольку реализация многих из них в Postgres Pro Enterprise может отличаться от других СУБД или вовсе не иметь аналогов. Например, пакеты, которые появились в версии 15, не являются прямыми аналогами пакетов Oracle — их синтаксис и возможности различаются.

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

## Page 5: Миграция данных {#source-page-005}

**SQL**
  - выгрузка + psql
- Обертки сторонних данных
  - универсальные для СУБД: ODBC, JDBC
  - для реляционных СУБД: Oracle (oracle\_fdw), MS SQL (tds\_fdw), MySQL,
  - DB2, SQLite
  - для NoSQL-СУБД: MongoDB, Redis, Cassandra
  - файловые: file\_fdw, CSV, JSON

### Комментарии преподавателя

При миграции данных из других СУБД можно использовать SQL как промежуточный формат. Конечно, это самый универсальный подход, но на практике при значительных объемах данных он неприменим. К тому же из-за разницы в диалектах SQL может потребоваться дополнительное преобразование данных и команд.

Для удобства работы со скриптами, часто применяемыми при такой миграции, утилита psql в Postgres Pro Enterprise может передавать им при вызове именованные и позиционные параметры.

<https://postgrespro.ru/docs/enterprise/16/app-psql#APP-PSQL-META-COM> MAND-INCLUDE

Дополнительные удобства и более высокую производительность можно получить, используя механизм оберток сторонних данных (foreign data wrappers), встроенный в PostgreSQL и позволяющий обращаться к внешним данным как к локальным таблицам. Штатная обертка file\_fdw позволяет читать данные из файлов различных форматов. В составе дистрибутива Postgres Pro Enterprise присутствует пакет oracle-fdw-ent-16 с расширением oracle\_fdw, устанавливающий одноименную обертку, и пакет tds-fdw-ent-16 для подключения к Microsoft SQL Server. Помимо этого, существует множество сторонних оберток для различных СУБД и форматов файлов.

<https://wiki.postgresql.org/wiki/Foreign\_data\_wrappers>

## Page 6: Параметры при вызове скрипта в утилите psql {#source-page-006}

```sh
student$ psql demo
```
Начиная с 15-й версии Postgres Pro Enterprise поддерживается передача именованных и позиционных параметров при вызове скрипта в утилите psql.
Если передается «имя=значение», создается переменная с указанным именем. Если указано только значение, оно присваивается позиционной переменной с именем PSQL\_ARG1, PSQL\_ARG2 и т. д. Именованные и позиционные параметры можно использовать одновременно.
Для демонстрации создадим файл example.sql:
```text
/home/student/tmp/example.sql
```
```text
\echo :schema
\echo :table
\echo :PSQL_ARG1
```
```sql
SELECT flight_id, flight_no departure_airport, arrival_airport, status, aircraft_code
FROM :schema.:table
WHERE flight_id = :PSQL_ARG1;
```
Перед выполнением запроса скрипт выводит значения трех переменных, переданных через параметры. Подразумевается, что первые два параметра будут именованными, а последний — позиционным.
Запустим скрипт из psql:
```text
=> \i ~/tmp/example.sql schema=bookings table=flights 20
```
```text
bookings
flights
20
 flight_id | departure_airport | arrival_airport | status  | aircraft_code
-----------+-------------------+-----------------+---------+---------------
        20 | PG0403            | LED             | Arrived | 321
(1 row)
```

## Page 7: Системные пакеты Oracle {#source-page-007}

**Расширение orafce**
  - функции, представления
  - пакеты dbms\_output, dbms\_sql, dbms\_pipe, dbms\_alert, dbms\_utility,
  - dbms\_assert, utl\_file
  - и др.
- Реализация других системных пакетов Oracle
  - dbms\_lob, dbms\_application\_info
  - utl\_mail, utl\_smtp, utl\_http

### Комментарии преподавателя

В дистрибутив Postgres Pro Enterprise включен пакет orafce-ent-16, устанавливающий расширение orafce. Оно добавляет в базу данных Postgres Pro Enterprise объекты, аналогичные объектам СУБД Oracle, что сильно упрощает перенос процедурной логики.

<https://github.com/orafce/orafce>

Несколько расширений, эмулирующих другие системные пакеты Oracle, поставляются в отдельном пакете pgpro-orautl-ent-16:

● utl\_mail — управление электронными письмами;

● utl\_smtp — отправка электронных писем из PL/pgSQL;

● utl\_http — выполнение HTTP-вызовов из SQL и PL/pgSQL.

<https://postgrespro.ru/docs/enterprise/16/utl-mail>

<https://postgrespro.ru/docs/enterprise/16/utl-smtp>

<https://postgrespro.ru/docs/enterprise/16/utl-http>

Еще два расширения добавлены в состав Postgres Pro Enterprise как стандартные и включены в основной пакет:

● dbms\_lob — работа с большими объектами: BLOB, CLOB, BFILE и временными LOB;

● pgpro\_application\_info — реализация пакета dbms\_application\_info.

<https://postgrespro.ru/docs/enterprise/16/dbms-lob>

<https://postgrespro.ru/docs/enterprise/16/pgpro-application-info>

## Page 8: Системные пакеты Oracle {#source-page-008}

Для примера рассмотрим работу с расширением pgpro\_application\_info, возможности которого можно использовать для анализа производительности и отладки приложений. Расширение содержит ряд подпрограмм, позволяющих приложениям сообщать о своем состоянии и ходе выполнения. Доступ к этой информации осуществляется через представления.
Начнем с установки расширения:
```sql
=> ALTER SYSTEM SET shared_preload_libraries = 'pgpro_application_info';
```
```sql
ALTER SYSTEM
```
Необходима перезагрузка экземпляра:
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
```sh
student$ psql demo
```
Добавим расширение в базу данных.
```sql
=> CREATE EXTENSION pgpro_application_info;
```
```sql
CREATE EXTENSION
```
В транзакции первого сеанса будем вызывать процедуры из расширения pgpro\_application\_info:
set\_client\_info — задает информацию о клиенте, например его название и/или описание; set\_module — передает имя выполняемого в данный момент модуля (либо подпрограммы) и действие в нем; set\_action — передает название выполняющегося действия в текущем модуле.
Во втором сеансе будем проверять состояние первого, используя представление v\_session того же расширения:
```sh
student$ psql demo
```
Первый сеанс:
```text
=> BEGIN;
```
```text
BEGIN
```
```text
=> CALL dbms_application_info.set_client_info('Первый сеанс');
```
```text
CALL
```
```text
=> CALL dbms_application_info.set_module('Модуль подсчета', 'Подготовка');
```
```text
CALL
```
Второй сеанс:
```sql
=> SELECT * FROM v_session;
```
```text
  sid   | dbname |     module      |   action   | client_info
--------+--------+-----------------+------------+--------------
 792743 | demo   | Модуль подсчета | Подготовка | Первый
сеанс
(1 row)
```
```text
=> CALL dbms_application_info.set_action('Подсчет');
```
```text
CALL
```
```sql
=> SELECT * FROM v_session;
```
```text
  sid   | dbname |     module      | action  | client_info
--------+--------+-----------------+---------+--------------
 792743 | demo   | Модуль подсчета | Подсчет | Первый
сеанс
(1 row)
```
Обратите внимание, что расширение работает нетранзакционно — в ряде случаев это может оказаться удобным.
```text
=> CALL dbms_application_info.set_module(NULL, NULL);
```
```text
CALL
```
```sql
=> SELECT * FROM v_session;
```

## Page 9: Page 9 {#source-page-009}

```text
  sid   | dbname | module | action | client_info
--------+--------+--------+--------+--------------
 792743 | demo   |        |        | Первый сеанс
(1 row)
```
Откатим транзакцию в первом сеансе:
```text
=> ROLLBACK;
```
```text
ROLLBACK
```

## Page 10: Пакеты {#source-page-010}

![Source slide page 10: Пакеты](images/page-010.png){#source-figure-010 caption="Source slide page 10: Пакеты"}


### Комментарии преподавателя

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

Спецификация и тело пакета — объекты базы данных Oracle.

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

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

В PostgreSQL аналогичной цели — группировке логически связанных объектов — служат схемы. Однако схема не имеет переменных и состояния, что очень сильно усложняет миграцию. Поэтому в Postgres Pro Enterprise реализован основной функционал пакетов. Он не повторяет пакеты Oracle синтаксически, а построен на основе схем.

<https://postgrespro.ru/docs/enterprise/16/packages-overview>

## Page 11: Пакеты {#source-page-011}

**Схема с функцией инициализации**
- Состояние
  - объявленные в \_\_init\_\_ переменные
- Аналог спецификации
  - заголовки публичных подпрограмм
  - типы данных
  - #export-переменные из \_\_init\_\_ (по умолчанию все)
- Аналог тела
  - публичные подпрограммы
  - внутренние #private-подпрограммы

### Комментарии преподавателя

Пакет в PostgresPro Enterprise — это схема, организованная специальным образом. Сначала в схеме создается функция с именем \_\_init\_\_ – функция инициализации.

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

Затем создаются пакетные подпрограммы – их помечают модификатором #package. По умолчанию такие подпрограммы будут публичными. Если же подпрограмма служит только для внутренних нужд пакета, ее следует пометить модификатором #private.

При обращении к любой пакетной подпрограмме вызывается функция инициализации, которая формирует состояние пакета. Сбросить его можно вызовом функции инициализации или plpgsql\_reset\_packages (это аналог DBMS\_SESSION.RESET\_PACKAGES в Oracle).

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

Пакет удобно создавать специальной командой CREATE PACKAGE.

<https://postgrespro.ru/docs/enterprise/16/plpgsql-package>

## Page 12: Пакеты {#source-page-012}

Создадим пакет, предоставляющий локальный для сеанса счетчик:
```sql
=> CREATE PACKAGE demo
```
```sql
  -- в команде CREATE PACKAGE все подпрограммы считаются пакетными,
  -- модификатор #package не нужен
  CREATE FUNCTION __init__() RETURNS void AS
  $$
  DECLARE
    n integer;
  BEGIN
    n := 0;
    RAISE NOTICE 'Пакет инициализирован';
  END;
  $$ -- точка с запятой только в конце пакета
  CREATE FUNCTION next() RETURNS integer AS
  $$
  BEGIN
    n := n + 1;
    RETURN n;
  END;
  $$
;
```
```sql
CREATE PACKAGE
```
При первом обращении к пакету выполняется функция инициализации:
```sql
=> SELECT demo.next();
```
```text
NOTICE:  Пакет инициализирован
 next
------
    1
(1 row)
```
```sql
=> SELECT demo.next();
```
```text
 next
------
    2
(1 row)
```
В другом сеансе отсчет начинается заново:
```sh
student$ psql demo
```
```sql
=> SELECT demo.next();
```
```text
NOTICE:  Пакет инициализирован
 next
------
    1
(1 row)
```
А в первом сеансе счетчик продолжает увеличиваться:
```sql
=> SELECT demo.next();
```
```text
 next
------
    3
(1 row)
```
Пакеты в Postgres Pro Enterprise реализованы как схемы. Поэтому в списке схем можно увидеть и схему demo:
```text
=> \dn
```

## Page 13: Page 13 {#source-page-013}

```text
              List of schemas
         Name          |       Owner
-----------------------+-------------------
 bookings              | student
 dbms_application_info | student
 demo                  | student
 public                | pg_database_owner
(4 rows)
```
Список схем-пакетов можно получить запросом, выводящим схемы, в которых есть функция \_\_init\_\_:
```sql
=> SELECT n.nspname AS schema_name
FROM pg_proc p
  JOIN pg_namespace n ON p.pronamespace = n.oid
WHERE p.proname = '__init__';
```
```text
 schema_name
-------------
 demo
(1 row)
```
Удалим пакет:
```sql
=> DROP PACKAGE demo;
```
```sql
DROP PACKAGE
```

## Page 14: Утилита ora2pgpro {#source-page-014}

**Автоматизация миграции из Oracle**
- Конвертация кода PL/SQL
  - пакеты, функции и процедуры, триггеры
  - автономные транзакции
  - VARRAY, ассоциативные массивы
- Перенос схемы данных и объектов
  - параллельная выгрузка и загрузка данных
  - секционированные таблицы (по спискам и по диапазонам, подсекции)
  - BLOB, пользовательские типы данных
  - поддержка DBLINK, SYNONYM, DIRECTORY
  - полнотекстовый поиск
  - Oracle Spatial (пространственные данные)

### Комментарии преподавателя

Утилита ora2pgpro предназначена для автоматизации конвертации кода и переноса объектов из СУБД Oracle в Postgres Pro Enterprise.

Утилита ora2pgpro создана на основе ora2pg:

<https://ora2pg.darold.net/documentation.html>

Однако ora2pgpro существенно расширяет возможности ora2pg по переносу кода и типов данных, отсутствующих в PostgreSQL, но реализованных в Postgres Pro Enterprise. Помимо этого, в ora2pgpro устранены ошибки, найденные за время эксплуатации ora2pg.

Некоторые из поддерживаемых возможностей перечислены на слайде. Полный список и все настройки описаны в документации:

<https://postgrespro.ru/docs/ora2pgpro/26/index>

Для работы утилиты требуется Oracle Instant Client Package.

Утилита ora2pgpro не поддерживается на платформе ARM64 (MacBook с процессором Apple Silicon) и в виртуальной машине курса для этой платформы отсутствует.

## Page 15: Утилита ora2pgpro {#source-page-015}

![Source slide page 15: Утилита ora2pgpro](images/page-015.png){#source-figure-015 caption="Source slide page 15: Утилита ora2pgpro"}


### Комментарии преподавателя

Утилита ora2pgpro подключается к БД Oracle, извлекает из нее структуру базы, данные и хранимый код (все вместе или по частям), и генерирует SQL-скрипты, которые потом можно загрузить в Postgres Pro Enterprise с помощью psql. В простых случаях, не требующих ручных правок, можно сформировать объекты напрямую в базе Postgres Pro Enterprise.

Утилита управляется директивами, которые позволяют переименовывать таблицы и столбцы в схеме данных, заменять типы данных (например, CHAR(1) на boolean, если он используется для логических значений) и т. д.

Для работы с хранимым кодом (пакетами, процедурами и функциями, триггерами) в утилиту добавлен транслятор, который разбирает код PL/SQL, строит дерево разбора и генерирует по нему код PL/pgSQL, используя все возможности, предоставляемые Postgres Pro Enterprise для совместимости с Oracle.

## Page 16: ora2pgpro {#source-page-016}

Утилита ora2pgpro уже установлена в виртуальной машине курса:
```sh
student$ ora2pgpro -v
```
```text
Ora2PgPro v26.1.1
```
Утилита может работать без подключения к БД Oracle, если необходимые данные заранее выгружены в файлы.
Создадим каталог, в котором будут находиться исходные данные для конвертации:
```sh
student$ mkdir -p ~/tmp/sources
```
Поместим в него два скрипта, описывающие простой пакет Oracle:
```text
/home/student/tmp/sources/DEMO_PKG_spec_source.sql
```
```text
-- спецификация пакета
PACKAGE demo_pkg AS
  FUNCTION next RETURN NUMBER;
END demo_pkg;
```
```text
/home/student/tmp/sources/DEMO_PKG_body_source.sql
```
```text
-- тело пакета
PACKAGE BODY demo_pkg
AS
  n NUMBER; -- состояние
```
```text
  FUNCTION next RETURN NUMBER IS
  BEGIN
    n := n + 1;
    RETURN n;
  END next;
```
```text
BEGIN
  -- инициализаци
  n := 0;
END demo_pkg;
```
Спецификация и тело пакета располагаются в подкаталоге sources каталога, который мы укажем утилите. В этот же каталог утилита выведет результаты своей работы.
```sh
student$ ls ~/tmp/sources
```
```text
DEMO_PKG_body_source.sql
DEMO_PKG_spec_source.sql
```
Утилите также потребуется конфигурационный файл, в котором указываются параметры-директивы, управляющие ее работой и описывающие подключение к базам Oracle и Postgres Pro. Мы собираемся запустить утилиту в локальном режиме, поэтому не будем указывать параметры подключения к базе данных Oracle и файл будет коротким:
```text
/home/student/tmp/ora2pgpro.conf
```
```text
PG_VERSION 16
```
При запуске указываем тип экспорта PACKAGE (пакеты) и пути к каталогу миграции и к конфигурационному файлу:
```sh
student$ ora2pgpro --offline -t PACKAGE -b ~/tmp -c ~/tmp/ora2pgpro.conf
```
```text
DEMO_PKG...
Done.
Fixing function calls in output files...
```
Сценарий — результат преобразования схемы — будет записан в файл:
```sh
student$ cat ~/tmp/result/DEMO_PKG.sql
```
```sql
-- спецификация пакета
BEGIN;
DROP SCHEMA IF EXISTS DEMO_PKG CASCADE;
CREATE SCHEMA DEMO_PKG;
-- тело пакета
```

## Page 17: Page 17 {#source-page-017}

```sql
CREATE OR REPLACE FUNCTION DEMO_PKG.__INIT__() RETURNS VOID AS $$
#package
#export off
DECLARE
```
```text
  n numeric; -- состояние
```
```text
BEGIN
  -- инициализаци
  n = 0;
END;
$$ LANGUAGE plpgsql;
```
```sql
  CREATE OR REPLACE FUNCTION DEMO_PKG.next() RETURNS numeric AS $$
  #package
  BEGIN
    DEMO_PKG.n = DEMO_PKG.n + 1;
    RETURN DEMO_PKG.n;
  END ; $$ LANGUAGE PLPGSQL;
/*END demo_pkg;*/
```
```text
-- спецификация пакета
COMMIT;
```
Выполним этот файл с помощью psql:
```sh
student$ psql -d demo < ~/tmp/result/DEMO_PKG.sql
```
```sql
BEGIN
NOTICE:  schema "demo_pkg" does not exist, skipping
DROP SCHEMA
CREATE SCHEMA
CREATE FUNCTION
CREATE FUNCTION
COMMIT
```
В базе данных появилась новая схема-пакет с необходимыми функциями:
```sql
=> SELECT n.nspname AS schema_name
FROM pg_proc p
  JOIN pg_namespace n ON p.pronamespace = n.oid
WHERE p.proname = '__init__';
```
```text
 schema_name
-------------
 demo_pkg
(1 row)
```
```text
=> \df demo_pkg.*
```
```text
                          List of functions
  Schema  |   Name   | Result data type | Argument data types | Type
----------+----------+------------------+---------------------+------
 demo_pkg | __init__ | void             |                     | func
 demo_pkg | next     | numeric          |                     | func
(2 rows)
```

## Page 18: Итоги {#source-page-018}

**Миграция с других СУБД — сложная задача**
- Postgres Pro Enterprise облегчает миграцию с Oracle
  - функционал пакетов
  - утилита ora2pgpro для автоматизации переноса данных и кода
  - аналоги системных пакетов Oracle
  - параметры при вызове скрипта в утилите psql

## Page 19: Практика {#source-page-019}

1. Создайте базу данных и добавьте в нее расширение orafce. 2. Какие схемы появились после загрузки расширения? 3. Изучите возможности функции dbms\_random.string.

### Комментарии преподавателя

1. Пакет orafce-ent-16 уже установлен в виртуальной машине.

3. С документацией по orafce можно ознакомиться в репозитории

<https://github.com/orafce/orafce>

## Page 20: 1. Добавление расширения orafce {#source-page-020}

```sh
student$ psql
```
Создадим базу данных pgpro\_migration и подключимся к ней:
```sql
=> CREATE DATABASE pgpro_migration;
```
```sql
CREATE DATABASE
```
```sql
=> \c pgpro_migration
```
```text
You are now connected to database "pgpro_migration" as user "student".
```
Расширение orafce распространяется в отдельном пакете orafce-ent-16, который уже установлен в виртуальной машине курса. Поэтому для установки расширения в базу данных достаточно выполнить команду CREATE EXTENSION:
```sql
=> CREATE EXTENSION orafce;
```
```sql
CREATE EXTENSION
```
### 2. Проверка доступных функций
Расширение orafce представляет реализации многих функций, которые существуют в СУБД Oracle, но отсутствуют (или реализованы по-другому) в Postgres Pro. Функции каждого из пакетов располагаются в отдельных схемах:
```text
=> \dn
```
```text
         List of schemas
     Name     |       Owner
--------------+-------------------
 dbms_alert   | student
 dbms_assert  | student
 dbms_output  | student
 dbms_pipe    | student
 dbms_random  | student
 dbms_sql     | student
 dbms_utility | student
 oracle       | student
 plunit       | student
 plvchr       | student
 plvdate      | student
 plvlex       | student
 plvstr       | student
 plvsubst     | student
 public       | pg_database_owner
 utl_file     | student
(16 rows)
```
### 3. Функция dbms\\\_random.string
Пакет dbms\_random предназначен для генерации случайных чисел и строк. Посмотрим, какие функции в него входят:
```text
=> \df dbms_random.*
```

## Page 21: Page 21 {#source-page-021}

```text
                                        List of functions
   Schema    |    Name    | Result data type |             Argument data types
 | Type
-------------+------------+------------------+--------------------------------------------
-+------
 dbms_random | initialize | void             | integer
 | func
 dbms_random | normal     | double precision |
 | func
 dbms_random | random     | integer          |
 | func
 dbms_random | seed       | void             | integer
 | func
 dbms_random | seed       | void             | text
 | func
 dbms_random | string     | text             | opt text, len integer
 | func
 dbms_random | terminate  | void             |
 | func
 dbms_random | value      | double precision |
 | func
 dbms_random | value      | double precision | low double precision, high double
precision | func
(9 rows)
```
Функция string возвращает случайные строки. Ее первый параметр однобуквенный, он отвечает за вид возвращаемого значения:
U/u — строка в верхнем регистре; L/l — строка в нижнем регистре; A/a — строка в смешанном регистре; X/x — строка из буквенно-цифровых символов в верхнем регистре; P/p — строка из любых печатных символов в смешанном регистре.
Второй параметр управляет длиной строки:
```sql
=> SELECT * FROM dbms_random.string('u',10);
```
```text
   string
------------
 BVREXBZUMB
(1 row)
```
```sql
=> SELECT * FROM dbms_random.string('l',10);
```
```text
   string
------------
 rfgsookawm
(1 row)
```
```sql
=> SELECT * FROM dbms_random.string('a',10);
```
```text
   string
------------
 ubvMWYlrcH
(1 row)
```
```sql
=> SELECT * FROM dbms_random.string('x',10);
```
```text
   string
------------
 F3G3AC694N
(1 row)
```
```sql
=> SELECT * FROM dbms_random.string('p',10);
```
```text
   string
------------
 hGX&/m8V,?
(1 row)
```
### Уборка
Удалим созданную базу данных.

## Page 22: Page 22 {#source-page-022}

```sql
=> \c student
```
```text
You are now connected to database "student" as user "student".
```
```sql
=> DROP DATABASE pgpro_migration WITH (FORCE);
```
```sql
DROP DATABASE
```
