Как нормализовать историю заказа фотостудии в SQL Oracle
При проектировании базы данных для фотостудии часто возникает задача хранить историю изменений заказа - особенно обновления статусов. Многие разработчики сталкиваются с проблемой, когда исходная модель использует JSON-атрибуты, с которыми сложно работать. В этой статье мы подробно разберём, как преобразовать сущность истории заказа в реляционную структуру с простыми типами данных (varchar2, number, boolean) на SQL Oracle.
Почему стоит отказаться от JSON в истории заказов
JSON удобен для хранения неструктурированных данных, но для истории заказов фотостудии он создаёт несколько проблем:
- Сложность написания запросов - требуется знание JSON-функций Oracle (JSON_VALUE, JSON_TABLE).
- Снижение производительности при фильтрации и сортировке по отдельным полям.
- Трудности с поддержкой и валидацией данных в долгосрочной перспективе.
Использование нормализованной схемы с простыми колонками упрощает разработку и делает код более читаемым.
Нормализованная структура таблицы истории заказов
Вместо одного JSON-поля предлагаем создать отдельную таблицу order_history с такими атрибутами:
- id (NUMBER) - первичный ключ, автоинкремент.
- order_id (NUMBER) - внешний ключ к таблице заказов.
- status (VARCHAR2) - новый статус заказа (например, 'NEW', 'PROCESSING', 'COMPLETED').
- changed_date (DATE) - дата и время изменения.
- changed_by (VARCHAR2) - пользователь или система, выполнившие обновление.
- is_active (NUMBER(1)) - булевый флаг, указывающий, является ли запись текущим статусом (1 - да, 0 - нет).
Это полностью реляционная модель без JSON.
Пример создания таблицы в SQL Developer
Ниже приведён DDL-скрипт для Oracle, который создаёт нормализованную таблицу истории заказов:
CREATE TABLE order_history (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
order_id NUMBER NOT NULL,
status VARCHAR2(50) NOT NULL,
changed_date DATE DEFAULT SYSDATE,
changed_by VARCHAR2(100),
is_active NUMBER(1) DEFAULT 1,
CONSTRAINT fk_order FOREIGN KEY (order_id) REFERENCES orders(id)
);Как заполнять таблицу при обновлении статуса
При каждом изменении статуса заказа необходимо выполнить две операции:
- Установить is_active = 0 для предыдущей активной записи.
- Вставить новую запись с is_active = 1 и новым статусом.
Пример PL/SQL-блока:
BEGIN
UPDATE order_history SET is_active = 0
WHERE order_id = :order_id AND is_active = 1;
INSERT INTO order_history (order_id, status, changed_by)
VALUES (:order_id, :new_status, :user);
COMMIT;
END;Получение полной истории заказа
Чтобы в любой момент увидеть все изменения по заказу, выполните простой SELECT:
SELECT id, status, changed_date, changed_by, is_active
FROM order_history
WHERE order_id = :order_id
ORDER BY changed_date DESC;Этот запрос возвращает все записи, включая информацию о том, какой статус активен сейчас (is_active = 1).
Преимущества реляционного подхода
- Простота - используются только базовые типы данных Oracle.
- Быстрые запросы - можно легко фильтровать по статусу, дате или пользователю.
- Понятная структура - любой разработчик, знакомый с SQL, сможет работать с таблицей без изучения JSON-функций.
Таким образом, вы полностью избавляетесь от JSON и получаете гибкую, производительную систему хранения истории заказов для фотостудии.