Oracle Заполнение резервной таблицы из основной таблицы
Вопрос
Программа, в которой я сейчас работаю, требует, чтобы я копировал содержимое таблицы в резервную таблицу перед реальной обработкой.
Во время проверки кода коллега отметил, что
INSERT INTO BACKUP_TABLE
SELECT *
FROM PRIMARY_TABLE
неоправданно рискованно, поскольку таблицы могут иметь разные столбцы и разный порядок столбцов.
Я также ограничен в том, чтобы не создавать/удалять/переименовывать таблицы.~Вздох~
Ожидается, что столбцы в таблице изменятся, поэтому простое жесткое кодирование имен столбцов на самом деле не является тем решением, которое я ищу.
Я ищу идеи о разумном и безопасном способе выполнить эту работу.
Решение
Таблица резервных копий остается рядом? Сохраняет ли он данные постоянно или это просто копия текущих значений?
Слишком плохо из-за невозможности создать / удалить / переименовать / скопировать. В противном случае, если это короткий срок, просто используется в случае, если что-то идет не так, то вы можете отбросить его в начале обработки и сделать что-то вроде
create table backup_table as select * from primary_table;
Лучшим вариантом может быть сделать выбор явным, как
insert into backup_table (<list of columns>) select <list of columns> from primary_table;
Вы можете сгенерировать это, построив строку SQL из словаря данных, а затем выполнив немедленно. Но вы все равно будете в опасности, если backup_table не содержит все важные столбцы из primary_table. Р>
Возможно, вам захочется сделать это явным и вызвать серьезную ошибку, если backup_table не существует или какой-либо из столбцов в primary_table отсутствует в backup_table. Р>
Другие советы
Как часто вы меняете структуру своих таблиц? Ваш метод должен работать нормально, если структура не меняется. Лично я думаю, что ваши администраторы баз данных должны предоставить вам механизм для удаления резервной таблицы и ее воссоздания, такой как хранимая процедура. На моей последней работе у нас было нечто похожее для усечения определенных таблиц, поскольку усечение часто намного быстрее, чем DELETE FROM TABLE;
.
Есть ли причина, по которой вы не можете просто перечислить столбцы в таблицах? Так
INSERT INTO backup_table( col1, col2, col3, ... colN )
SELECT col1, col2, col3, ..., colN
FROM primary_table
Конечно, для этого необходимо повторно просмотреть код при изменении определения одной из таблиц, чтобы определить, нужно ли вносить изменения в код, но, как правило, это небольшая цена за изоляцию от различий в порядке столбцов, различия в именах столбцов и несоответствующие различия в определениях таблиц.
Если бы у меня была такая ситуация, я бы получил определения столбцов для двух таблиц в самом начале проблемы. Тогда, если бы они были идентичны, я бы начал с простого:
INSERT INTO BACKUP_TABLE
SELECT *
FROM PRIMARY_TABLE
Если бы они были другими, я бы продолжил, только если бы не было критических столбцов, отсутствующих в резервной таблице. В этом случае я бы использовал эту форму для резервной копии:
INSERT INTO BACKUP_TABLE (<list of columns>)
SELECT <list of columns>
FROM PRIMARY_TABLE
Но я бы также беспокоился о том, что произойдет, если я просто остановлю программу с ошибкой, поэтому у меня даже может быть план резервного копирования, в котором я буду использовать вторую форму для столбцов, находящихся в обеих таблицах, а также для дампа текстовый файл с PK и столбцами, отсутствующими в резервной копии. Также зарегистрируйте ошибку, даже если кажется, что программа завершилась нормально. Таким образом, вы можете восстановить данные, если произойдет худшее.
Действительно, это признак плохих процессов где-то, которые следует устранить, но защитное программирование может помочь сделать это проблемой кого-то другого, а не вашей. Если они не замечают сообщение об ошибке в журнале, которое сообщает им о дампе текста с отсутствующими столбцами, то это не ваша ошибка. Р>
Но если вы не защитите код, и произойдет худшее, это будет частично ваша вина.
Вы можете попробовать что-то вроде:
CREATE TABLE secondary_table AS SELECT * FROM primary_table;
Не уверен, что это автоматически копирует данные.Если не:
CREATE TABLE secondary_table AS SELECT * FROM primary_table LIMIT 1;
INSERT INTO secondary_table SELECT * FROM primary_table;
Редактировать:
Извините, не до конца прочитал Ваш пост:особенно часть ограничений.Боюсь, я не знаю как.Я предполагаю, что будет использоваться процедура, которая сначала описывает обе таблицы и сравнивает их, прежде чем создавать длинный запрос на вставку/выбор.
Тем не менее, если вы используете резервную таблицу, я думаю, очень важно, чтобы она точно соответствовала исходной.