Комментарии 9
Чет как будто не проще просто экспортировать бд файлом .sql, а затем просто воссоздать из файла бд?
Ну или там другой какой-нибудь формат
А что делать, если в цикле ты удаляешь данные из базы, а они не вставляются в новую, ты же теряешь данные насовсем, разве это безопасно?
Чет как будто не проще просто экспортировать бд файлом .sql, а затем просто воссоздать из файла бд?
Ну или там другой какой-нибудь формат
А зачем экспорт/импорт, если линки между БД настроены?
А что делать, если в цикле ты удаляешь данные из базы, а они не вставляются в новую, ты же теряешь данные насовсем, разве это безопасно?
При работе ETL всегда есть база-источник с исходными данными и база приемник. Данные на источнике в этом случае не теряются, так как из нее они только селектятся.
Самый малоиспользуемый цикл, как по мне, это do..while. За свою двадцатилетнюю карьеру он мне раза 2 понадобился, когда с ним вот прямо проще было. Даже уже и не припомню конкретные ситуации...
В первом примере лучше питоновское множество (set)
использовать в качестве check_list
и удалять из него успешно обработанные объекты. А так вы на каждой итерации только при вычислении условия цикла по всему списку проходитесь и ещё лишние итерации делаете, проверяя признак для уже обработанных объектов.
Это было бы действительно хорошей идеей, если бы множество было упорядоченным.
Лучше добавлять объекты в конец списка, расширяя его, благо while терпим к такому.
Получилось бы так (см. листинг), но тогда теряется идея чек-листа:
etl_objects = [('MY_SCHEMA', 'MY_TABLE1'), ('MY_SCHEMA', 'MY_TABLE2'), ...]
i = 0
while i < len(etl_objects):
try:
with cx_Oracle.connect(user=user,
password=password,
tns=tns,
encoding='utf-8') as db_conn:
with db_conn.cursor() as cursor:
sql_text = (f"delete from {etl_objects[i][0]}.{etl_objects[i][1]} "
"where my_column = 'my_variable'")
cursor.execute(sql_text)
cursor.execute('commit')
sql_text = (f"insert into {etl_objects[i][0]}.{etl_objects[i][1]} "
"select * "
f"from {etl_objects[i][0]}.{etl_objects[i][1]}@src_dblink "
"where my_column = 'my_variable';")
cursor.execute(sql_text)
сursor.execute('commit')
except Exception as e:
print(f"Сработало исключение {str(e)}: объект загрузки отправлен в конец очереди")
etl_objects.append(etl_objects[i])
i += 1
Соединение достаточно открывать одно, а не переоткрывать на каждой итерации.
Лишние фиксации, замедляют код, мешают атомарности и отсутствие транзакций
Не вижу отката транзакции при возникшем исключении.
Соединение достаточно открывать одно, а не переоткрывать на каждой итерации.
Это дело вкуса, в моём случае, когда за одно соединение переносится таблица весом в 1 ГБ, не так уж важно, закрою я его перед переносом следующей таблицы, или нет.
Лишние фиксации, замедляют код, мешают атомарности и отсутствие транзакций
Не вижу отката транзакции при возникшем исключении.
Здесь явное противоречие, если я уже перенес 99% таблиц и на последней у меня возникло исключение, да еще и закрылась транзакция rollback, то выходит я зря сделал 99% работы. В oracle возникшее исключение автоматически откатывает транзакцию (так настроена БД, например, в PSQL есть понятие автокоммитов). Кроме того, не закрытая транзакция никакого вреда данным не наносит, если не лочит таблицы. В моем случае таблицы не лочатся.
Где циклу while нет альтернативы