使用pyodbc和SQLAlchemy连接SQL Server时USE语句报错求助
解决SQLAlchemy+pyodbc执行
USE database_name语句的问题 这个报错的核心原因是:当你在一个session.execute()里执行多条SQL语句时,SQLAlchemy会返回第一个语句的结果对象——而USE语句是不返回任何行的,所以当你尝试遍历这个空结果时就会触发错误。下面给你几个可行的解决方案:
方案1:分开执行USE和查询语句
既然USE是用来切换当前连接的数据库上下文,你可以把它单独执行一次,之后再执行查询语句:
import urllib import sqlalchemy from sqlalchemy.orm import sessionmaker, scoped_session def list_dbs(): try: odbc_connect = "DRIVER={SQL Server};Server=localhost;Database=master;port=1433" engine = sqlalchemy.create_engine("mssql+pyodbc:///?odbc_connect=%s" % urllib.quote_plus(odbc_connect), echo=True, connect_args={'autocommit': True}) SessionFactory = sessionmaker(bind=engine) session = scoped_session(SessionFactory) # 先执行切换数据库的语句 session.execute("use master;") # 再执行查询,此时上下文已经是master库 result = session.execute("SELECT name FROM sys.databases;") for v in result: print(v) except Exception as e: print(e) list_dbs()
方案2:使用原生pyodbc游标处理多结果集
如果你一定要在一个语句里执行多个SQL,可以通过engine.raw_connection()获取原生的pyodbc连接,然后手动切换结果集:
import urllib import sqlalchemy def list_dbs(): sql = """ use master; SELECT name FROM sys.databases; """ try: odbc_connect = "DRIVER={SQL Server};Server=localhost;Database=master;port=1433" engine = sqlalchemy.create_engine("mssql+pyodbc:///?odbc_connect=%s" % urllib.quote_plus(odbc_connect), echo=True, connect_args={'autocommit': True}) # 获取原生连接和游标 with engine.raw_connection() as conn: with conn.cursor() as cursor: cursor.execute(sql) # 跳过第一个语句(USE)的空结果集 cursor.nextset() # 读取第二个语句的查询结果 result = cursor.fetchall() for v in result: print(v) except Exception as e: print(e) list_dbs()
方案3:避免使用USE,直接指定数据库前缀
如果只是查询不同库的表,你也可以不用切换数据库,直接在查询中用数据库名.架构名.表名的方式访问:
# 不需要USE语句,直接查询master库的sys.databases result = session.execute("SELECT name FROM master.sys.databases;")
补充说明
SQLAlchemy的ORM会话对多语句的处理是偏向单结果集场景的,而USE这类DDL语句本身不会返回行,所以混合执行时会出现结果对象为空的问题。上面的方案要么拆分语句、要么直接操作原生游标,都能绕过这个限制,满足你切换多个数据库的需求。
内容的提问来源于stack exchange,提问作者mutoulion
相关产品推荐
相关产品推荐

