Как стать автором
Обновить

Комментарии 9

Чет как будто не проще просто экспортировать бд файлом .sql, а затем просто воссоздать из файла бд?

Ну или там другой какой-нибудь формат

А что делать, если в цикле ты удаляешь данные из базы, а они не вставляются в новую, ты же теряешь данные насовсем, разве это безопасно?

Чет как будто не проще просто экспортировать бд файлом .sql, а затем просто воссоздать из файла бд?

Ну или там другой какой-нибудь формат

А зачем экспорт/импорт, если линки между БД настроены?

А что делать, если в цикле ты удаляешь данные из базы, а они не вставляются в новую, ты же теряешь данные насовсем, разве это безопасно?

При работе ETL всегда есть база-источник с исходными данными и база приемник. Данные на источнике в этом случае не теряются, так как из нее они только селектятся.

Самый малоиспользуемый цикл, как по мне, это do..while. За свою двадцатилетнюю карьеру он мне раза 2 понадобился, когда с ним вот прямо проще было. Даже уже и не припомню конкретные ситуации...

Удобно для работы с paginated response

Да, это прям топчик когда нужен цикл с пагинацией.

В первом примере лучше питоновское множество (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. Соединение достаточно открывать одно, а не переоткрывать на каждой итерации.

  2. Лишние фиксации, замедляют код, мешают атомарности и отсутствие транзакций

  3. Не вижу отката транзакции при возникшем исключении.

Соединение достаточно открывать одно, а не переоткрывать на каждой итерации.

Это дело вкуса, в моём случае, когда за одно соединение переносится таблица весом в 1 ГБ, не так уж важно, закрою я его перед переносом следующей таблицы, или нет.

Лишние фиксации, замедляют код, мешают атомарности и отсутствие транзакций

Не вижу отката транзакции при возникшем исключении.

Здесь явное противоречие, если я уже перенес 99% таблиц и на последней у меня возникло исключение, да еще и закрылась транзакция rollback, то выходит я зря сделал 99% работы. В oracle возникшее исключение автоматически откатывает транзакцию (так настроена БД, например, в PSQL есть понятие автокоммитов). Кроме того, не закрытая транзакция никакого вреда данным не наносит, если не лочит таблицы. В моем случае таблицы не лочатся.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории