Как нормализовать историю заказа фотостудии в 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)
    );

    Как заполнять таблицу при обновлении статуса

    При каждом изменении статуса заказа необходимо выполнить две операции:

    1. Установить is_active = 0 для предыдущей активной записи.
    2. Вставить новую запись с 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 и получаете гибкую, производительную систему хранения истории заказов для фотостудии.

    Часто задаваемые вопросы