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

168
16 ноября 2020, 17:40

Задача такая, по логике моего приложения, (оно уже работает), нужно подключиться к базе и проверить, соответствует ли таблицы в базе, к которой я подключаюсь, той структуре базы данных, которая содержится в моем приложении, и если таблица не соответствует то изменить ее. Логически задача простая, но база у меня Oracle, и так как я новичок, то чтобы избежать потери времени хочу узнать, как лучше делать такое сравнение. Есть у меня TOAD (лягушка), и в ней есть механизм сравнения структур таблиц, казалось бы бери структуру и сравнивай, но вопрос в том, как алгоритмически построить правильно функцию для сравнения, которую я затем встрою в свое приложение, может есть какие то уже готовые решения именно для Оракла. Также отмечу, что нужна сохранность данных. Данные не должны теряться.

Answer 1

Вижу несколько вариантов:
1. Пересоздание таблицы:
Проверяем, есть ли таблица с таким именем:

SELECT t.table_name       
FROM   dba_tables t       
WHERE  t.owner = 'your_owner' 
and    t.table_name = 'your_table' 
ORDER  BY t.table_name;

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

2. Сравнивать версии таблицы:
Для промышленной эксплуатации чаще всего не допустимо делать все время drop\create. Мы создавали отдельную таблицу, которая хранила версии нашего продукта. В патчах установки был прописан алгоритм поведения в зависимости от версии. В результате в наших исходника таблица создавалась только первый раз, а все остальные накаты содержали скрипты модификации исходной таблицы

3. Если очень хочется универсально анализировать изменения таблицы:
3.1 Есть различные продукты для выполнения похожих задач, например от RED GATE.
3.2 Если очень хочется самому, можно получить скрипт создания таблицы из системного словаря
3.2.1 из таблиц в БД.
Можно писать свои запросы из dba_tables, dba_columns, dba_tab_cols и других Некоторые скрипты для этого можно найти тут, например скрипт table_defs.sql покажет часть определения таблицы:

SELECT table_name,
       column_id,
       column_name,
       data_type,
       (CASE
         WHEN data_type IN ('VARCHAR2','CHAR') THEN TO_CHAR(data_length)
         WHEN data_scale IS NULL OR data_scale = 0 THEN TO_CHAR(data_precision)
         ELSE TO_CHAR(data_precision) || ',' || TO_CHAR(data_scale)
       END) "SIZE",
       DECODE(nullable, 'Y', '', 'NOT NULL') nullable
FROM   user_tab_columns
WHERE  table_name = DECODE(UPPER('&1'), 'ALL', table_name, UPPER('&1'))
ORDER  BY table_name, column_id;

Этот запрос захватывает далеко не все из определения таблицы. Но он указывает направление поиска. Отдельно надо будет поискать индексы, constraint'ы, выданные на таблицу привилегии и возможно что-то еще
3.2.2 Использовать пакет DBMS_METADATA для получения исходников. Например для начала:

DBMS_METADATA.GET_DDL('TABLE', 'YOUR_TABLE_NAME') from dual

UPD на основе комментариев
Вы хотите при старте приложения каждый раз проверять структуру БД и обновлять ее при необходимости. Такой подход обязательно приведет к проблемам, это просто вопрос времени. Однажды у вас окажется, что после обновления приложения версия БД новее вашего приложения. И вы испортите ваши данные. Это обязательно случится, кто-то случайно накатит не ту версию или просто подключится более старой версией приложения. В общем это вопрос не если, а когда.

Рассмотрите разделение установки и ежедневной эксплуатации и введите версионность приложения и структуры БД.
Таким образом вы получите ряд дополнительных возможностей:
1. И БД и приложение будут обновляться одновременно.
2. Вы сможете проверять совместимость версии приложения с версией БД и не запускать в ситуациях, когда нет полной совместимости.
3. Среду разработки можно восстанавливать из бэкапа прома(при необходимости обезличивая). Дальше вы просто обновляете БД до разрабатываемой версии приложения.
4. Вы частично обезопаситесь от ошибок людей разворачивающих ваше приложение.

READ ALSO
mysql объединение двух таблиц

mysql объединение двух таблиц

есть две таблицы user

167
Doctrine - постоянное соединение с базой данных PostgeSQL

Doctrine - постоянное соединение с базой данных PostgeSQL

Не могу понять, как работает соединение с БД в DoctrineИспользую Symfony 4, запущен встроенный php-сервер

172