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

如何让pyodbc忽略SQL Server的PRINT/RAISERROR消息以避免查询错误?

解决pyodbc执行含PRINT/RAISERROR脚本时fetchall报错的问题

核心原因

ODBC驱动不会把PRINT或RAISERROR('...', 0, 1)的内容判定为错误,这些只是信息级消息。但pyodbc会把每条这类消息当成一个空的"结果集",当你直接调用fetchall()时,cursor还停留在第一个空结果集上,就会触发ProgrammingError: No results. Previous SQL was not a query.错误。

可行解决方案

1. 跳过空结果集,定位到有效查询结果

执行SQL后,用cursor.nextset()循环跳过所有空的消息结果集,直到找到真正的查询结果:

cursor.execute(your_sql_script)

# 跳过所有非查询的空结果集
while cursor.nextset():
    pass

# 现在可以正常获取查询结果
results = cursor.fetchall()

注意:如果脚本包含多个查询结果集,这个方法会跳过前面所有结果,只保留最后一个。如果需要保留多个结果,得调整逻辑逐个判断。

2. 保留调试消息同时获取结果

如果想保留这些调试消息,可先读取cursor.messages属性获取消息内容,再处理结果集:

cursor.execute(your_sql_script)

# 读取并输出所有调试消息
for msg in cursor.messages:
    print(f"调试信息: {msg[1]}")

# 切换到有效结果集
while cursor.nextset():
    pass

results = cursor.fetchall()

如果messages未自动填充,结合循环处理更可靠:

cursor.execute(your_sql_script)

# 遍历所有结果集,处理消息并定位到有效数据
while True:
    # 读取当前结果集的调试消息
    for msg in cursor.messages:
        print(f"调试信息: {msg[1]}")
    # 切换到下一个结果集,没有则退出循环
    if not cursor.nextset():
        break

# 最后获取查询结果
results = cursor.fetchall()

补充说明

  • SET NOCOUNT ON这类语句只能抑制计数消息,对PRINT和RAISERROR(0,1)无效,这也是你遇到无法用SET禁用所有消息的原因。
  • 若脚本有多个查询结果,需要根据实际需求调整nextset()的循环逻辑,避免误删需要的结果。

内容的提问来源于stack exchange,提问作者Armando Contestabile

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:55:03