Подтвердить что ты не робот

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

Как я могу выполнить весь sql файл в базе данных с помощью SQLAlchemy? В файле может быть много разных sql-запросов, включая begin и commit/rollback.

4b9b3361

Ответ 1

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

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

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

Ответ 2

Если вы используете sqlite3, у него есть полезное расширение для dbapi, называемое conn.executescript(str), я подключил его через что-то вроде этого, и он, казалось, работал: (Не показан весь контекст, но этого должно быть достаточно для получения дрейфа)

def init_from_script(script):
    Base.metadata.drop_all(db_engine)
    Base.metadata.create_all(db_engine)     

    # HACK ALERT: we can do this using sqlite3 low level api, then reopen session.
    f = open(script)
    script_str = f.read().strip()
    global db_session
    db_session.close()
    import sqlite3
    conn = sqlite3.connect(db_file_name)
    conn.executescript(script_str)
    conn.commit()

    db_session = Session()

Является ли это чистое зло? Я тщетно искал "чистый" sqlalchemy эквивалент, возможно, который мог быть добавлен в библиотеку, что-то вроде db_session.execute_script (имя_файла)? Я надеюсь, что db_session будет работать отлично после всего этого (т.е. Не нужно перезапускать движок), но пока не уверен... необходимы дальнейшие исследования (т.е. Нам нужно получить новый движок или просто сеанс после выхода за sqlalchemy назад?)

FYI sqlite3 включает связанную процедуру: sqlite3.complete_statement (sql), если вы катите свой собственный парсер...

Ответ 3

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

    # Open the .sql file
    sql_file = open(<file.sql>,'r')

    # Create an empty command string
    sql_command = ''

    # Iterate over all lines in the sql file
    for line in sql_file:
        # Ignore comented lines
        if not line.startswith('--') and line.strip('\n'):
            # Append line to the command string
            sql_command += line.strip('\n')

            # If the command string ends with ';', it is a full statement
            if sql_command.endswith(';'):
                # Try to execute statemente and commit it
                try:
                    session.execute(text(sql_command))
                    session.commit()

                # Assert in case of error
                except:
                    print('Ops')

                # Finally, clear command string
                finally:
                    sql_command = ''

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