在SQLAlchemy中从文件执行SQL

Szy*_*ski 22 sql database sqlalchemy

如何使用SQLAlchemy将整个sql文件执行到数据库中?文件中可以有许多不同的sql查询,包括begin和commit/rollback.

Ale*_*eue 8

您可以使用 SQLalchemy 和 psycopg2 来完成。

file = open(path)
engine = sqlalchemy.create_engine(db_url)
escaped_sql = sqlalchemy.text(file.read())
engine.execute(escaped_sql)
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于所有方言。SQLite 例如明确禁止在一个“执行”命令中执行多个查询。 (2认同)

小智 7

我能够使用纯SQLAlchemy和一些字符串操作来运行.sql模式文件.它肯定不是一个优雅的方法,但它的工作原理.

# 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 commented 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 statement 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 = ''
Run Code Online (Sandbox Code Playgroud)

它遍历.sql文件中忽略注释行的所有行.然后它连接形成完整语句的行并尝试执行该语句.您只需要一个文件处理程序和一个会话对象.


Erf*_*fan 6

使用 sqlalchemy.sql.text

.sql通过使用内置text构造,有一种更直接的方法来执行文件。

from sqlalchemy import create_engine
from sqlalchemy.sql import text

engine = create_engine('mysql://{USR}:{PWD}@localhost:3306/db', echo=True)

with engine.connect() as con:
    file = open("src/models/query.sql")
    query = text(file.read())

    con.execute(query)
Run Code Online (Sandbox Code Playgroud)


Ant*_*sma 5

不幸的是,我没有一个好的通用答案。某些dbapi(例如psycopg2)支持一次执行许多语句。如果文件不是很大,您可以将它们加载到字符串中并在连接上执行它们。对于其他用户,我将尝试为该数据库使用命令行客户端,并使用subprocess模块​​将数据通过管道传递给该客户端。

如果这些方法不可接受,则必须继续执行一个小型SQL解析器,该解析器可以将文件拆分为单独的语句。要确保100%正确,这确实很棘手,因为您必须考虑数据库方言特定的文字转义规则,所使用的字符集以及任何影响文字解析的数据库配置选项(例如PostgreSQL standard_conforming_strings)。

如果您只需要99.9%的正确率,那么一些正则表达式魔术应该可以帮助您达到目标。


Car*_*rlS 5

如果您使用的是 sqlite3,它有一个名为 conn.executescript(str) 的有用的 dbapi 扩展,我已经通过类似这样的东西将其连接起来,它似乎有效:(未显示所有上下文,但它应该足以获得漂移)

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()
Run Code Online (Sandbox Code Playgroud)

我想知道这是纯粹的邪恶吗?我徒劳地寻找“纯”sqlalchemy 等价物,也许可以将其添加到库中,例如 db_session.execute_script(file_name) ?我希望 db_session 在这一切之后能够正常工作(即不需要重新启动引擎)但还不确定......需要进一步研究(即我们是否需要获得一个新引擎或只是在 sqlalchemy 背后进行一次会话?)

仅供参考 sqlite3 包括一个相关的例程: sqlite3.complete_statement(sql) 如果您使用自己的解析器...


Dav*_*vid 5

您可以通过此访问原始 DBAPI 连接

    raw_connection = mySqlAlchemyEngine.raw_connection()
    raw_cursor = raw_connection() #get a hold of the proxied DBAPI connection instance
Run Code Online (Sandbox Code Playgroud)

但这取决于您使用的方言/驱动程序,可以通过此列表进行参考。

对于 pyscog2,你可以这样做

    raw_cursor.execute(open("my_script.sql").read())
Run Code Online (Sandbox Code Playgroud)

但是 pysqlite 你需要做

    raw_cursor.executescript(open("my_script").read())
Run Code Online (Sandbox Code Playgroud)

根据这一点,您需要检查您正在使用的 DBAPI 驱动程序的文档,以查看一次执行中是否允许多个语句,或者您是否需要使用executescriptpysqlite 特有的帮助程序。