【问题标题】:pyodbc & MS SQL Server - "No results. Previous SQL was not a query."pyodbc & MS SQL Server - “没有结果。以前的 SQL 不是查询。”
【发布时间】:2013-04-09 04:07:19
【问题描述】:

我正在使用 pyodbc 从 Microsoft SQL Server 检索数据。查询格式如下

SET NOCOUNT ON --Ignore count statements

CREATE TABLE mytable ( ... )

EXEC some_stored_procedure
INSERT mytable

--Perform some processing...

SELECT *
FROM mytable

存储过程对包含NULLs 的值执行一些聚合,从而发出Warning: Null value is eliminated by an aggregate or other SET operation. 形式的警告。这会导致 pyodbc 无法检索数据并显示错误消息 No results. Previous SQL was not a query.

我尝试通过设置SET ANSI_WARNINGS OFF 来禁用警告。但是,查询随后会失败并显示错误消息 Heterogeneous queries require the ANSI_NULLS and ANSI_WARNINGS options to be set for the connection. This ensures consistent query semantics. Enable these options and then reissue your query.

可以吗

  • 禁用警告
  • 还是让 pyodbc 忽略警告?

请注意,我没有更改存储过程的权限。

【问题讨论】:

  • 语句之间不需要分号吗? ;?我是真心问的。我不知道。
  • @JoeFrambach:不,不需要分号。

标签: python sql-server pyodbc


【解决方案1】:

将查询结果存储在临时表中,并将语句作为两个查询执行:

with pyodbc.connect(connection_string) as connection:
    connection.execute(query1)            #Do the work
    result = connection.execute(query2)   #Select the data
    data = result.fetchall()              #Retrieve the data

第一个查询完成了繁重的工作,格式为

--Do some work and execute complicated queries that issue warning messages

--Store the results in a temporary table
SELECT some, column, names
INTO #datastore
FROM some_table

第二个查询检索数据,格式为

SELECT * FROM #datastore

因此,在执行第一个查询时会发出所有警告消息。它们不会在执行第二个查询期间干扰数据检索。

【讨论】:

  • Till 的上述回答不起作用,因为即使连接没有被删除,第二个查询也不知道该表是什么。但是,如果您使用全局临时表,它就可以工作。例如:##datastore
  • 这似乎很奇怪,因为临时表的范围是每个会话 (msdn.microsoft.com/en-us/library/ms174979.aspx) 而不是每个查询。您是否正在放弃会话但保持连接有效?我会警告不要使用全局临时表,因为多个用户同时执行相同的查询可能会导致冲突。
【解决方案2】:

我已经通过在有问题的视图或存储过程周围打开和关闭 ansi_warnings 来减轻这个错误。

/* vw_someView aggregates away some nulls and presents warnings that blow up pyodbc */
set ANSI_WARNINGS off
select *
into #my_temp
from vw_someView
set ANSI_WARNINGS on

/* rest of query follows */

这假定产生聚合警告的实体也不需要打开警告。如果它抱怨,这可能意味着实体本身有一部分这样的代码需要切换 ansi_warnings(或重写以消除聚合。)

一个问题是,如果我尝试将它作为跨服务器查询运行,我发现此切换仍然返回“异构”警告。此外,在调试时,很容易进入 ansi_warnings 在您没有意识到的情况下被关闭的状态,并且您似乎无缘无故地开始出现异构错误。只需运行“设置 ANSI_WARNINGS on”行,即可让自己恢复到良好状态。

【讨论】:

    【解决方案3】:

    最好是加上try: except: block

    sql="sp_help stored_procedure;"
    print(">>>>>executing {}".format(sql))
    next_cursor=cursor.execute(sql)
    while next_cursor:
    try:
        row = cursor.fetchone()
        while row:
            print(row)
            row = cursor.fetchone()
    except Exception as my_ex:
        print("stored procedure returning non-row {}".format(my_ex))
    next_cursor=cursor.nextset() 
    

    【讨论】:

      猜你喜欢
      • 2013-08-21
      • 2011-12-06
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-09
      • 1970-01-01
      相关资源
      最近更新 更多