Oracle Database — корпоративная реляционная СУБД

Oracle Database — одна из самых распространённых корпоративных систем управления базами данных в мире. Она используется в банках, ритейле и госсекторе благодаря высокой надёжности, масштабируемости и мощному языку PL/SQL.

Уровень: средний 18 разделов ⏱ 3–4 часа

1. Что такое Oracle Database

Oracle Database (часто называют просто Oracle) — объектно-реляционная СУБД, разрабатываемая корпорацией Oracle с конца 1970-х годов. Это первая коммерческая система, поддерживающая язык SQL, и сегодня она занимает лидирующие позиции на рынке корпоративных баз данных.

Где применяется Oracle

ОбластьПримеры использования
Банки и финансыучётные системы, транзакции, отчётность
Ритейлкаталоги товаров, логистика, аналитика продаж
Государственный секторреестры, порталы услуг
ERP и CRMOracle E-Business Suite, PeopleSoft, Siebel
В отличие от бесплатных PostgreSQL и MySQL, Oracle в основном распространяется на коммерческой основе. Для обучения и небольших проектов существует бесплатная редакция Oracle XE.

2. Редакции Oracle и установка

Oracle выпускается в нескольких редакциях, отличающихся функциональностью и стоимостью лицензии:

РедакцияОписание
Enterprise Edition (EE)полный набор функций для крупных корпораций
Standard Edition (SE)базовый набор для среднего бизнеса
Express Edition (XE)бесплатная версия для обучения и разработки
Oracle Cloudуправляемая БД как сервис в облаке

Для изучения подойдёт Oracle XE (Express Edition). Скачай установщик с официального сайта oracle.com и запусти его. Во время установки будут заданы пароли для системных пользователей — обязательно их запомни.

Установщик Oracle XE под Windows требует права администратора и сразу ставит и сервер, и клиентский инструмент SQL*Plus. На Linux установка выполняется через RPM-пакеты, а на macOS — только через Docker.
Самый простой способ попробовать Oracle на любом компьютере — запустить официальный образ в Docker:
docker run -d --name oracle-xe \
  -p 1521:1521 -p 5500:5500 \
  -e ORACLE_PASSWORD=oracle \
  container-registry.oracle.com/database/express:latest

3. Подключение и SQL*Plus

SQL*Plus — консольный клиент Oracle. Он устанавливается вместе с базой и позволяет выполнять SQL-команды и PL/SQL-скрипты. Подключение к базе выглядит так:

sqlplus username/password@host:port/service

Например, для подключения к локальной Oracle XE с системной учётной записью system:

sqlplus system/oracle@localhost:1521/XEPDB1
В новой Oracle XE используется двухуровневая архитектура: сервис XEPDB1 — это пользовательская (pluggable) база данных, а XE — контейнерная база CDB. В примерах подключайся к XEPDB1.

Полезные команды SQL*Plus:

DESC employees;        -- описание структуры таблицы
SHOW USER;             -- текущий пользователь
SELECT * FROM TAB;     -- список таблиц пользователя
SET LINESIZE 180;      -- ширина вывода
SET PAGESIZE 50;       -- высота страницы вывода

4. Таблицы и типы данных

Таблицы создаются командой CREATE TABLE. Первичный ключ обычно делают на основе последовательности SEQUENCE, поскольку автоинкремента как в MySQL у Oracle по умолчанию нет:

CREATE TABLE products (
    id          NUMBER(10)     NOT NULL,
    name        VARCHAR2(100)  NOT NULL,
    price       NUMBER(10, 2),
    created_at  TIMESTAMP      DEFAULT SYSTIMESTAMP,
    CONSTRAINT pk_products PRIMARY KEY (id)
);

CREATE SEQUENCE seq_products START WITH 1 INCREMENT BY 1;

Основные типы данных Oracle

ТипОписание
NUMBER(p, s)число с точностью p и масштабом s (деньги)
VARCHAR2(n)текст длиной до n байт (обязательно указывать длину)
CHAR(n)фиксированный текст
DATEдата и время
TIMESTAMPдата и время с долями секунды
CLOBбольшой текст до 4 ГБ
BLOBдвоичные данные до 4 ГБ
BOOLEANTRUE / FALSE (условно, как NUMBER(1))
В Oracle не существует типа VARCHAR в «чистом» виде — он объявлен как тип-псевдоним, и использовать его не рекомендуется. Всегда пиши VARCHAR2(n).

5. Вставка и выборка данных

Вставка данных в Oracle выполняется как в стандартном SQL. Сгенерированное значение ключа берётся из последовательности через NEXTVAL:

INSERT INTO products (id, name, price)
VALUES (seq_products.NEXTVAL, 'Ноутбук', 79990.00);

COMMIT;
В отличие от MySQL, в Oracle транзакции нужно заканчивать явной командой COMMIT. Пока она не выполнена, изменения видны только внутри текущей сессии.

Выборка с фильтрацией и сортировкой:

SELECT name, price
FROM products
WHERE price > 10000
ORDER BY price DESC;

Ограничение количества строк реализуется через псевдостолбец ROWNUM или через фетчинг (Oracle 12c и новее):

SELECT name, price
FROM products
ORDER BY price DESC
FETCH FIRST 10 ROWS ONLY;
Синтаксис LIMIT, знакомый по MySQL и PostgreSQL, в Oracle не работает. Используй FETCH FIRST n ROWS ONLY или фильтр по ROWNUM.

6. Основы PL/SQL

PL/SQL — процедурное расширение SQL для Oracle. Программа состоит из блоков с секциями объявлений (DECLARE), тела (BEGIN) и обработки исключений (EXCEPTION). Простейший блок:

SET SERVEROUTPUT ON;

DECLARE
    v_name  VARCHAR2(50);
    v_price NUMBER(10, 2);
BEGIN
    SELECT name, price
      INTO v_name, v_price
      FROM products
     WHERE id = 1;

    DBMS_OUTPUT.PUT_LINE(v_name || ' стоит ' || v_price);
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('Продукт не найден');
END;
/

Команда SELECT ... INTO кладёт значения из одной строки в переменные, а DBMS_OUTPUT.PUT_LINE выводит текст на экран (если включён вывод, см. SET SERVEROUTPUT ON).

Управляющие конструкции

В PL/SQL доступны привычные IF, CASE и циклы FOR / WHILE:

DECLARE
    v_total NUMBER := 0;
BEGIN
    FOR i IN 1..5 LOOP
        v_total := v_total + i;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('Сумма 1..5 = ' || v_total);
END;
/

7. Процедуры и функции

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

CREATE OR REPLACE PROCEDURE add_product (
    p_name  IN  VARCHAR2,
    p_price IN  NUMBER,
    p_id    OUT NUMBER
) IS
BEGIN
    INSERT INTO products (id, name, price)
    VALUES (seq_products.NEXTVAL, p_name, p_price)
    RETURNING id INTO p_id;
    COMMIT;
END;
/

Вызов процедуры из блока:

DECLARE
    new_id NUMBER;
BEGIN
    add_product('Мышь', 1990.00, new_id);
    DBMS_OUTPUT.PUT_LINE('Добавлен продукт id=' || new_id);
END;
/

Функция обязана возвращать значение через RETURN:

CREATE OR REPLACE FUNCTION avg_price
RETURN NUMBER IS
    v_avg NUMBER(10, 2);
BEGIN
    SELECT AVG(price) INTO v_avg FROM products;
    RETURN v_avg;
END;
/

SELECT avg_price FROM DUAL;
В SELECT-выражениях Oracle всегда нужен псевдотаблица DUAL. Это служебная таблица из одной строки, к которой обращаются, когда данные из реальных таблиц не требуются.

8. Индексы и производительность

Индексы ускоряют поиск и сортировку. Базовый B-tree индекс создаётся так же, как в других СУБД:

CREATE INDEX idx_products_name ON products (name);

Для уникального столбца индекс можно создать сразу при создании таблицы:

CREATE TABLE users (
    id     NUMBER(10)     NOT NULL,
    email  VARCHAR2(200)  NOT NULL,
    CONSTRAINT uq_users_email UNIQUE (email),
    CONSTRAINT pk_users PRIMARY KEY (id)
);

Чтобы посмотреть, как выполняется запрос, используй EXPLAIN PLAN — он строит план выполнения в таблицу планов:

EXPLAIN PLAN FOR
SELECT name FROM products WHERE name = 'Ноутбук';

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
План выполнения показывает, каким путём сервер достаёт данные: полное сканирование таблицы (FULL TABLE SCAN) или поиск по индексу (INDEX RANGE SCAN). Если в колонке много уникальных значений, индекс почти всегда выгоднее.

Для текстового поиска подходит инвертированный индекс Oracle Text, а для карт — пространственные индексы. Выбор правильного типа индекса зависит от вида данных и запросов.

9. Транзакции и изоляция

Оracle строго соблюдает свойства ACID. Все изменения внутри транзакции либо применяются целиком (команда COMMIT), либо откатываются (команда ROLLBACK):

BEGIN  -- начало транзакции (неявное)

UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

COMMIT;  -- или ROLLBACK при ошибке

Точки сохранения SAVEPOINT позволяют откатить часть транзакции, не отменяя её целиком:

INSERT INTO products (id, name) VALUES (seq_products.NEXTVAL, 'Колонка');
SAVEPOINT sp_before_price;

UPDATE products SET price = 100 WHERE name = 'Колонка';
ROLLBACK TO sp_before_price;  -- цена не обновится, продукт останется
Oracle использует многоверсионное чтение (MVCC): читатели не блокируют писателей, а писатели не блокируют читателей. Уровень изоляции по умолчанию — READ COMMITTED.

Сравнение транзакционных команд

КомандаДействие
COMMITфиксирует все изменения текущей транзакции
ROLLBACKотменяет все изменения текущей транзакции
SAVEPOINT nameставит точку сохранения
ROLLBACK TO nameоткатывает изменения до точки сохранения
SET TRANSACTIONзадаёт уровень изоляции транзакции

10. Сравнение Oracle и PostgreSQL

Oracle — коммерческий гигант корпоративного мира, PostgreSQL — продвинутая свободная СУБД. Различия касаются не только цены, но и технических деталей:

КритерийOraclePostgreSQL
Лицензиякоммерческая (есть бесплатная XE)PostgreSQL License (open-source)
Процедурный языкPL/SQLPL/pgSQL (похож)
Тип текстаVARCHAR2(n)VARCHAR(n) / TEXT
АвтоинкрементSEQUENCEGENERATED ALWAYS AS IDENTITY
Ограничение строкROWNUM / FETCH FIRSTLIMIT / OFFSET
КластеризацияRACрепликация, патруттеры расширений
PL/SQL и PL/pgSQL очень похожи, поэтому, освоив один язык, легко перейти на другой. Главный фактор выбора между Oracle и PostgreSQL — бюджет проекта: в небольших стартапах почти всегда берут бесплатный PostgreSQL, в крупных корпорациях часто остаются на Oracle из-за поддержки вендора.

11. PL/SQL: пакеты и функции

PL/SQL встраивается в базу и выполняет бизнес-логику без передачи данных в приложение. Главная единица — пакет: спецификации (интерфейс) и тело (реализация). Изменение тела не требует перекомпиляции клиентов.

CREATE OR REPLACE PACKAGE order_api AS
  FUNCTION calc_total(p_id NUMBER) RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY order_api AS
  FUNCTION calc_total(p_id NUMBER) RETURN NUMBER IS
    v_sum NUMBER;
  BEGIN
    SELECT SUM(price * quantity) INTO v_sum
    FROM order_items WHERE order_id = p_id;
    RETURN v_sum;
  END;
END;
/
Пакет компилируется целиком, а процедуры работают быстрее отдельных функций: один вызов в SQL-контексте вместо серии обращений. Всегда используйте параметры через IN/OUT, а не глобальные переменные.
Логика в пакете выполняется с правами владельца (definer rights) по умолчанию. Учитывайте это при аудите доступа: процедура может читать таблицы, к которым вызывающий прямого права не имеет.

12. Массовые операции: BULK COLLECT и FORALL

Построчное выполнение FOR в PL/SQL делает тысячи переключений контекста SQL↔PL/SQL. BULK COLLECT и FORALL выполняют операции порциями и ускоряют массовую обработку до сотен раз.

DECLARE
  TYPE t_ids IS TABLE OF NUMBER;
  v_ids t_ids;
BEGIN
  SELECT id BULK COLLECT INTO v_ids
  FROM orders WHERE status = 'CLOSED' AND rownum <= 5000;

  FORALL i IN 1..v_ids.COUNT
    UPDATE order_archive
    SET archived_at = SYSDATE
    WHERE order_id = v_ids(i);

  COMMIT;
END;
/
Ошибка в FORALL по умолчанию прерывает цикл. Директива SAVE EXCEPTIONS собирает все ошибки в коллекцию, чтобы посчитать успешные строки и продолжить выполнение.
Ограничивайте порции через LIMIT (например 500 строк) и коммитьте с интервалом — так вы не подержите транзакцию долго за открытой и не разрастёте undo-журнал.

13. Аналитические функции

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

SELECT product_name, sale_date, amount,
       RANK()       OVER (PARTITION BY product_name
                          ORDER BY amount DESC)   AS rnk,
       SUM(amount)  OVER (PARTITION BY product_name
                          ORDER BY sale_date
                          ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
                                                    AS sales_3days
FROM sales;
Оконные функции дешевле самосоединений: они проходят таблицу один раз. Покрывайте PARTITION BY ... ORDER BY составным индексом, чтобы не терять выигрыш на сортировке.

14. Секционирование, материализованные представления и Oracle 23

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

CREATE TABLE log_entries (
  id NUMBER, ts DATE, msg VARCHAR2(4000)
)
PARTITION BY RANGE (ts) (
  PARTITION p2026_08 VALUES LESS THAN (DATE '2026-09-01'),
  PARTITION p2026_09 VALUES LESS THAN (DATE '2026-10-01')
);

CREATE MATERIALIZED VIEW mv_sales_monthly
REFRESH COMPLETE ON DEMAND AS
SELECT product_id, TRUNC(sale_date, 'MM') AS month,
       SUM(amount) amt
FROM sales GROUP BY product_id, TRUNC(sale_date, 'MM');
Materialized view ускоряет тяжёлые агрегаты в разы, но его надо обновлять по расписанию (DBMS_MVIEW.REFRESH) — не забывайте про актуальность данных в отчётах.
Oracle 23c привнёс SQL-объекты, AI Vector Search и анонимные блоки без / — но прежде чем переходить на новые фичи, проверьте совместимость версии у провайдера облака или лицензии on-premise.

Регулярно собирайте статистику (DBMS_STATS.GATHER_TABLE_STATS) и следите за AWR-отчётами продакшена: без свежей статистики оптимизатор выбирает плохие планы на, казалось бы, простых запросах.

15. Data Pump: миграция и перенос данных

Для переноса данных между базами Oracle служит утилита Data Pump: команды expdp и impdp выгружают и загружают схемы, таблицы или целые базы в компактном бинарном формате. В отличие от старого exp/imp, Data Pump работает на сервере и поддерживает параллельную выгрузку.

-- каталог для файлов дампа
CREATE OR REPLACE DIRECTORY dump_dir AS '/u01/dumps';

-- выгрузка схемы
expdp system/system@ORCL \
  schemas=app dumpfile=app.dmp directory=dump_dir \
  parallel=4 compression=all

-- импорт с заменой (drop existing)
impdp system/system@ORCL \
  schemas=app dumpfile=app.dmp directory=dump_dir \
  table_exists_action=replace

Перед миграцией проверьте параметры schema и remap_schema: имя пользователя в целевой базе может отличаться. Для пониженного RPO используйте transportable tablespaces или GoldenGate, а Data Pump подходит для плановых переносов между окружениями.

Правило бесстрессовой миграции: дамп принимается совместимой версией Oracle. Указывайте version=19c, если целевую базу собрали на другой версии.
Пароли в команде спалятся в истории shell. Используйте файл параметров или переменные окружения и права на чтение каталога не давайте лишним пользователям.

16. RMAN и стратегия восстановления

Recovery Manager (RMAN) — штатное средство бэкапов Oracle: он пишет копии файлов данных, архизов redis и управляет инкрементальными обновлениями. Команды просты, а план восстановления тестируется заранее на тестовой базе.

rman target /

RMAN> BACKUP DATABASE PLUS ARCHIVELOG;
RMAN> BACKUP INCREMENTAL LEVEL 0 DATABASE;
RMAN> BACKUP INCREMENTAL LEVEL 1
      FOR RECOVER OF COPY WITH TAG 'daily';

-- восстановление
RMAN> RESTORE DATABASE;
RMAN> RECOVER DATABASE;

Level 0 — полная базовая копия, level 1 — накопление изменений с неё. Раз в сутки есть смысл делать level 0, между ними — level 1, а для мгновенного восстановления используйте point-in-time c помощью меток SET UNTIL TIME.

УровеньЧто содержит
Level 0полная копия базы
Level 1изменения с Level 0
Archivelogперекрывающие изменения до точки сбоя
RMAN-бэкапы без теста восстановления бесполезны: храните каталог бэкапов на отдельном устройстве и ежемесячно выполняйте контрольное RESTORE на песочницу.

17. Listener, tnsnames и подключение приложений

Доступ к Oracle из приложений идёт через Listener — сетевой процесс, принимающий подключения по протоколу TNS. Файл tnsnames.ora описывает, как найти базу: хост, порт 1521 и имя сервиса. В коде соединение обычно задаётся строкой подключения или именем из tnsnames.

# tnsnames.ora
ORCL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.10)(PORT = 1521))
    (CONNECT_DATA = (SERVICE_NAME = ORCL)))

# проверка доступности
lsnrctl status

В Python используйте драйвер python-oracledb с режимом thin (без клиента) или thick (с полным клиентом Oracle): thin-режим достаточно для REST и большинства бизнес-приложений.

import oracledb

conn = oracledb.connect(
    user="app", password="secret",
    dsn="192.168.1.10:1521/ORCL")
cur = conn.cursor()
cur.execute("SELECT COUNT(*) FROM orders")
print(cur.fetchone()[0])
Не используйте пароль в открытом коде: вынесите в переменные окружения, а на проде — в secret-хранилище.
Проверяйте availability через tnsping и следите за логами listener на предмет ошибок авторизации.

18. Оптимизатор: статистика, планы и индексы

Оптимизатор Oracle выбирает план по статистике: количество строк, плотность, распределение значений. Свежая статистика — половина успеха; собирайте её регулярно через DBMS_STATS.GATHER_TABLE_STATS, особенно после массовых загрузок.

EXEC DBMS_STATS.GATHER_TABLE_STATS('APP', 'ORDERS');

-- план выполнения для запроса
EXPLAIN PLAN FOR
SELECT * FROM orders WHERE customer_id = 42 AND status = 'NEW';
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

Смотрите на операции: TABLE ACCESS FULL на большой таблице — повод добавить индекс, а INDEX RANGE SCAN — хорошая отправная точка. Создавайте составные индексы под точные сочетания WHERE и учитывайте порядок колонок; при отсутствии попадания добавьте EXPLAIN ANALYZE-уровень (в 19c через SQL Monitor) для данных из реального плана.

Мелкие таблицы оптимизатор предпочтёт сканировать целиком: индекс там не ускорит, а замедлит записи из-за накладных расходов на обновление.

Что дальше

Ты познакомился с Oracle Database: установкой XE, работой в SQL*Plus, таблицами и типами, основами PL/SQL, процедурами, индексами и транзакциями. Дальше стоит углубиться в язык запросов в уроке SQL и сравнить подходы с открытой СУБД в PostgreSQL. Если цены и лицензии Oracle пугают — изучи MySQL как бесплатную альтернативу для веб-проектов.

← Вернуться к курсам