0

Выполнение SQL из файла в SQLAlchemy

9

Как я могу выполнить целый SQL-файл в базе данных, используя SQLAlchemy? Файл может содержать множество различных SQL-запросов, включая команды BEGIN и COMMIT/ROLLBACK.

4 ответ(ов)

0

Я смог выполнить файлы схемы .sql, используя чистый SQLAlchemy и некоторые манипуляции со строками. Это, конечно, не самый элегантный подход, но он работает.

Вот пример кода:

# Открываем .sql файл
sql_file = open('file.sql', 'r')

# Создаём пустую строку для SQL-команды
sql_command = ''

# Проходим по всем строкам в .sql файле
for line in sql_file:
    # Игнорируем комментируемые строки
    if not line.startswith('--') and line.strip('\n'):
        # Добавляем строку к команде
        sql_command += line.strip('\n')

        # Если строка заканчивается на ';', это полное выражение
        if sql_command.endswith(';'):
            # Пытаемся выполнить выражение и зафиксировать изменения
            try:
                session.execute(text(sql_command))
                session.commit()

            # Обрабатываем ошибку, если она возникла
            except:
                print('Опс')

            # В конце очищаем строку команды
            finally:
                sql_command = ''

Этот код проходит по всем строкам в файле .sql, игнорируя строки с комментариями. Затем он конкатенирует строки, формирующие полное выражение, и пытается выполнить это выражение. Вам понадобятся только обработчик файла и объект сессии.

0

Вы можете сделать это с помощью SQLAlchemy и psycopg2. Вот пример кода:

file = open(path)
engine = sqlalchemy.create_engine(db_url)
escaped_sql = sqlalchemy.text(file.read())
engine.execute(escaped_sql)

Этот код открывает файл, считывает SQL-запрос и выполняет его с помощью SQLAlchemy. Убедитесь, что у вас правильно настроены db_url и установлены необходимые библиотеки (SQLAlchemy и psycopg2).

0

К сожалению, я не знаю хорошего общего ответа на этот вопрос. Некоторые реализации DBAPI (например, psycopg2) поддерживают выполнение нескольких операторов одновременно. Если файлы не слишком большие, вы можете просто загрузить их в строку и выполнить на соединении. Для других баз данных я бы попробовал использовать клиент командной строки для этой базы и передать данные через модуль subprocess.

Если эти способы вам не подходят, тогда вам придется реализовать небольшой SQL-парсер, который сможет разделить файл на отдельные операторы. Это довольно сложно сделать на 100% корректно, так как вам придется учитывать специфические правила экранирования литералов для разных диалектов SQL, кодировку символов и любые параметры конфигурации базы данных, которые могут влиять на разбор литералов (например, стандартные строки в PostgreSQL).

Если вам нужно добиться лишь 99.9% корректности, то немного магии с использованием регулярных выражений может помочь вам почти в полной мере справиться с этой задачей.

0

Ваш код действительно демонстрирует интересный подход к выполнению скриптов с помощью SQLite и SQLAlchemy. Тем не менее, стоит быть осторожным при использовании такого "хака". Вот некоторые мысли по этому поводу.

  1. Использование executescript: Ваша идея использовать conn.executescript(script_str) для выполнения многокомандного SQL скрипта является приемлемым решением для SQLite, однако это действительно отклонение от стандартного способа работы с SQLAlchemy. К тому же, такое решение может снизить уровень абстракции, предоставляемый SQLAlchemy, и привести к путанице в поддержании кода.

  2. Закрытие сессии: В вашем коде вы закрываете сессию перед выполнением скрипта. Это правильный шаг, чтобы избежать потенциальных конфликтов, но вы также должны быть уверены, что не осталось открытых транзакций или ресурсов. Если у вас есть активные транзакции, вам, возможно, придется откатить их, прежде чем закрыть сессию.

  3. Создание новой сессии: Вы правильно делаете, что создаете новую сессию после выполнения скрипта. SQLAlchemy не всегда может автоматически отслеживать изменения, внесенные непосредственно через драйвер, так что новосозданная сессия позволит избежать неожиданных проблем.

  4. Поиск альтернатив: На самом деле, если вам нужна возможность выполнять SQL-скрипты, вы можете создать свой метод в классе сессии для выполнения таких скриптов. Это поможет избежать использования низкоуровневых функций, сохранив при этом все преимущества SQLAlchemy.

  5. sqlite3.complete_statement(sql): Хорошо, что вы упомянули эту функцию. Она может быть полезной, если вы планируете разрабатывать свой собственный парсер или механизм выполнения. Но это требует больше работы и может добавить сложности.

В конечном счете, использование низкоуровневых API — это действенный, но не всегда предпочтительный метод. Лучше всего придерживаться абстракций, предложенных самой библиотекой SQLAlchemy, насколько это возможно. Если вам действительно нужно добавлять эту функциональность, лучше всего сделать это через интерфейсы, которые предоставляет SQLAlchemy.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь