SQL与SQLAlchemy.execute执行差异:MSSQL条件建表无响应问题
问题排查:SQLAlchemy执行MSSQL条件创建表无反应的原因
我之前也碰到过类似的问题,你的情况大概率和事务提交机制或者SQLAlchemy的执行逻辑有关,下面给你拆解原因和解决办法:
核心原因:事务未提交
SQLAlchemy的数据库连接默认是开启事务的,而直接在数据库客户端(比如SSMS)执行语句时,客户端默认会自动提交事务。当你用db_engine.execute()执行创建表的条件语句后,如果没有手动提交事务,这个操作会被悄悄回滚——看起来就像“无任何反应”,实际上表短暂被创建后又被撤销了。
解决方案1:手动提交事务
改用上下文管理器管理连接,执行后明确提交事务,这是SQLAlchemy 1.4+的推荐写法:
from sqlalchemy import text with db_engine.connect() as conn: sql_stmt = text(""" IF NOT EXISTS (select * from information_schema.tables where table_name='my_table') CREATE TABLE my_table (col1 float(53), col2 varchar(100), col3 varchar(10)) """) conn.execute(sql_stmt) conn.commit() # 关键步骤:手动提交事务
解决方案2:开启全局自动提交
如果你希望所有DDL操作都自动提交,可以在创建引擎时设置autocommit=True:
db_engine = sqlalchemy.create_engine( 'mssql+pyodbc:///?odbc_connect={}'.format(quoted), connect_args={"autocommit": True} ) # 之后执行语句无需手动提交 db_engine.execute(""" IF NOT EXISTS (select * from information_schema.tables where table_name='my_table') CREATE TABLE my_table (col1 float(53), col2 varchar(100), col3 varchar(10)) """)
额外排查点:表名匹配精度
虽然你直接执行SQL正常,但还是建议完善条件判断的SQL,加上数据库名和schema,避免因不同schema的同名表导致判断失误:
IF NOT EXISTS ( select * from information_schema.tables where TABLE_CATALOG = :db_name and TABLE_SCHEMA = 'dbo' and table_name='my_table' ) CREATE TABLE my_table (col1 float(53), col2 varchar(100), col3 varchar(10))
用参数绑定的方式传入数据库名更安全:
with db_engine.connect() as conn: sql_stmt = text(""" IF NOT EXISTS ( select * from information_schema.tables where TABLE_CATALOG = :db_name and TABLE_SCHEMA = 'dbo' and table_name='my_table' ) CREATE TABLE my_table (col1 float(53), col2 varchar(100), col3 varchar(10)) """) conn.execute(sql_stmt, {"db_name": database}) conn.commit()
补充:SQLAlchemy 2.0+版本注意事项
如果你用的是SQLAlchemy 2.0+,db_engine.execute()已经被弃用,必须使用engine.begin()上下文管理器,它会自动帮你提交事务:
with db_engine.begin() as conn: conn.execute(text(""" IF NOT EXISTS (select * from information_schema.tables where table_name='my_table') CREATE TABLE my_table (col1 float(53), col2 varchar(100), col3 varchar(10)) """)) # 无需手动commit,begin()上下文会自动完成提交
内容的提问来源于stack exchange,提问作者Esben Eickhardt
相关产品推荐
相关产品推荐

