You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLAlchemy 2.x操作MSSQL动态删建表时出现报错及语句不生效问题求助

SQLAlchemy 2.x操作MSSQL动态删建表时出现报错及语句不生效问题求助

我现在在使用SQLAlchemy 2.0.39 + Python 3.10.11做动态数据表的操作,已经成功通过下面的代码动态生成了映射类:

dynamic_class = type(table_name, (Base,), attributes)

现在我需要删除已存在的对应表,再用当前的类定义重建,但这一步出了问题。我写的删表和建表代码如下:

log.info(f"Dropping Table: mygrc.{table_name}")
dynamic_class.__table__.drop(dbEngine, checkfirst=True)

log.info(f"Creating Table: mygrc.{table_name}")
Base.metadata.create_all(dbEngine, tables=[dynamic_class.__table__])

但无论是删表还是建表操作,都抛出了同样的错误:

No results. Previous SQL was not a query.

后来我尝试直接把编译后的SQL语句传给execute执行,虽然不再报错,但语句根本没生效(即使手动commit了),代码是这样的:

with dbEngine.connect() as connection:
    create_table_statement = str(dynamic_class.__table__.compile(dbEngine))
    connection.execute(text(create_table_statement))

这里编译出来的create_table_statement是完全合法的建表语句,手动执行是有效的。

我还拿到了完整的报错栈:

Traceback (most recent call last):
  File "c:\Users\username\Documents\Coding\azure-pipeline\.venv\lib\site-packages\sqlalchemy\engine\base.py", line 1980, in _exec_single_context
    result = context._setup_result_proxy()
  File "c:\Users\username\Documents\Coding\azure-pipeline\.venv\lib\site-packages\sqlalchemy\engine\default.py", line 1838, in _setup_result_proxy
    strategy = _cursor.BufferedRowCursorFetchStrategy(
  File "c:\Users\username\Documents\Coding\azure-pipeline\.venv\lib\site-packages\sqlalchemy\engine\cursor.py", line 1188, in __init__
    self._rowbuffer = collections.deque(dbapi_cursor.fetchmany(1))
pyodbc.ProgrammingError: No results.  Previous SQL was not a query.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "c:\Users\username\.vscode\extensions\ms-python.debugpy-2025.4.1-win32-x64\bundled\libs\debugpy\__main__.py", line 71, in <module>
    cli.main()
  File "c:\Users\username\.vscode\extensions\ms-python.debugpy-2025.4.1-win32-x64\bundled\libs\debugpy/..\debugpy\server\cli.py", line 501, in main
    run()
  File "c:\Users\username\.vscode\extensions\ms-python.debugpy-2025.4.1-win32-x64\bundled\libs\debugpy/..\debugpy\server\cli.py", line 351, in run_file
    runpy.run_path(target, run_name="__main__")
  File "c:\Users\username\.vscode\extensions\ms-python.debugpy-2025.4.1-win32-x64\bundled\libs\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_runpy.py", line 310, in run_path
    return _run_module_code(code, init_globals, run_name, pkg_name=pkg_name, script_name=fname)
  File "c:\Users\username\.vscode\extensions\ms-python.debugpy-2025.4.1-win32-x64\bundled\libs\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_runpy.py", line 127, in _run_module_code
    _run_code(code, mod_globals, init_globals, mod_name, mod_spec, pkg_name, script_name)
  File "c:\Users\username\.vscode\extensions\ms-python.debugpy-2025.4.1-win32-x64\bundled\libs\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_runpy.py", line 118, in _run_code
    exec(code, run_globals)
  File "C:\Users\username\Documents\Coding\azure-pipeline\mygrcreport.py", line 94, in <module>
    mygrc_3ps_inherent_risk, primary_key = mygrcreport_db.dynamic_table(schema, "mygrc_3ps_inherent_risk", dbEngine)
  File "\mygrcreport_db.py", line 81, in dynamic_table
    dynamic_class.__table__.drop(dbEngine, checkfirst=True)
  File "\.venv\lib\site-packages\sqlalchemy\sql\schema.py", line 1301, in drop
    bind._run_ddl_visitor(ddl.SchemaDropper, self, checkfirst=checkfirst)
  File "\.venv\lib\site-packages\sqlalchemy\engine\base.py", line 3249, in _run_ddl_visitor
    conn._run_ddl_visitor(visitorcallable, element, **kwargs)
  File "\.venv\lib\site-packages\sqlalchemy\engine\base.py", line 2456, in _run_ddl_visitor
    visitorcallable(self.dialect, self, **kwargs).traverse_single(element)
  File "\.venv\lib\site-packages\sqlalchemy\sql\visitors.py", line 664, in traverse_single
    return meth(obj, **kw)
  File "\.venv\lib\site-packages\sqlalchemy\sql\ddl.py", line 1203, in visit_table
    DropTable(table)._invoke_with(self.connection)
  File "\.venv\lib\site-packages\sqlalchemy\sql\ddl.py", line 314, in _invoke_with
    return bind.execute(self)
  File "\.venv\lib\site-packages\sqlalchemy\engine\base.py", line 1416, in execute
    return meth(
  File "\.venv\lib\site-packages\sqlalchemy\sql\ddl.py", line 180, in _execute_on_connection
    return connection._execute_ddl(
  File "\.venv\lib\site-packages\sqlalchemy\engine\base.py", line 1527, in _execute_ddl
    ret = self._execute_context(
  File "\.venv\lib\site-packages\sqlalchemy\engine\base.py", line 1843, in _execute_context
    return self._exec_single_context(
  File "\.venv\lib\site-packages\sqlalchemy\engine\base.py", line 1983, in _exec_single_context
    self._handle_dbapi_exception(
  File "\.venv\lib\site-packages\sqlalchemy\engine\base.py", line 2352, in _handle_dbapi_exception
    raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
  File "\.venv\lib\site-packages\sqlalchemy\engine\base.py", line 1980, in _exec_single_context
    result = context._setup_result_proxy()
  File "\.venv\lib\site-packages\sqlalchemy\engine\default.py", line 1838, in _setup_result_proxy
    strategy = _cursor.BufferedRowCursorFetchStrategy(
  File "\.venv\lib\site-packages\sqlalchemy\engine\cursor.py", line 1188, in __init__
    self._rowbuffer = collections.deque(dbapi_cursor.fetchmany(1))
sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) No results.  Previous SQL was not a query.
[SQL:
DROP TABLE mygrc.mygrc_3ps_inherent_risk]

之后我尝试开启自动提交模式来执行删表操作,代码如下:

logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)
log.info(f"Dropping Table: mygrc.{table_name}")
with dbEngine.connect().execution_options(isolation_level='AUTOCOMMIT') as connection:
    connection.execute(text(f'DROP TABLE IF EXISTS mygrc.{table_name}'))

结果还是没生效,从日志里能看到明明执行了DROP语句,但最后还是触发了ROLLBACK,即使已经开了AUTOCOMMIT。日志内容如下:

2025-03-28 10:07:56,802 - INFO - Dropping Table: mygrc.mygrc_3ps_inherent_risk
2025-03-28 10:07:58,279 INFO sqlalchemy.engine.Engine SELECT CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR)
2025-03-28 10:07:58,279 - INFO - SELECT CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR)
2025-03-28 10:07:58,279 INFO sqlalchemy.engine.Engine [raw sql] ()
2025-03-28 10:07:58,279 - INFO - [raw sql] ()
2025-03-28 10:07:58,416 INFO sqlalchemy.engine.Engine SELECT schema_name()
2025-03-28 10:07:58,416 - INFO - SELECT schema_name()
2025-03-28 10:07:58,416 INFO sqlalchemy.engine.Engine [generated in 0.00073s] ()
2025-03-28 10:07:58,416 - INFO - [generated in 0.00073s] ()
2025-03-28 10:07:58,822 INFO sqlalchemy.engine.Engine SELECT CAST('test max support' AS NVARCHAR(max))
2025-03-28 10:07:58,822 - INFO - SELECT CAST('test max support' AS NVARCHAR(max))
2025-03-28 10:07:58,823 INFO sqlalchemy.engine.Engine [generated in 0.00052s] ()
2025-03-28 10:07:58,823 - INFO - [generated in 0.00052s] ()
2025-03-28 10:07:58,958 INFO sqlalchemy.engine.Engine SELECT 1 FROM fn_listextendedproperty(default, default, default, default, default, default, default)
2025-03-28 10:07:58,958 - INFO - SELECT 1 FROM fn_listextendedproperty(default, default, default, default, default, default, default)  
2025-03-28 10:07:58,959 INFO sqlalchemy.engine.Engine [generated in 0.00053s] ()
2025-03-28 10:07:58,959 - INFO - [generated in 0.00053s] ()
2025-03-28 10:08:35,716 INFO sqlalchemy.engine.Engine BEGIN (implicit; DBAPI should not BEGIN due to autocommit mode)
2025-03-28 10:08:35,716 - INFO - BEGIN (implicit; DBAPI should not BEGIN due to autocommit mode)
2025-03-28 10:08:35,716 INFO sqlalchemy.engine.Engine DROP TABLE IF EXISTS mygrc.mygrc_3ps_inherent_risk
2025-03-28 10:08:35,716 - INFO - DROP TABLE IF EXISTS mygrc.mygrc_3ps_inherent_risk
2025-03-28 10:08:35,717 INFO sqlalchemy.engine.Engine [generated in 0.00132s] ()
2025-03-28 10:08:35,717 - INFO - [generated in 0.00132s] ()
2025-03-28 10:08:43,022 INFO sqlalchemy.engine.Engine ROLLBACK using DBAPI connection.rollback(), DBAPI should ignore due to autocommit mode
2025-03-28 10:08:43,022 - INFO - ROLLBACK using DBAPI connection.rollback(), DBAPI should ignore due to autocommit mode

手动执行对应的SQL语句是完全没问题的,我的数据库账号也有足够的权限。有没有大佬能帮我分析下这是什么情况?

备注:内容来源于stack exchange,提问作者trevrobwhite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 20:14:34