MSSQL2008 - Pyodbc - 以前的 SQL 不是查询

Posted

技术标签:

【中文标题】MSSQL2008 - Pyodbc - 以前的 SQL 不是查询【英文标题】:MSSQL2008 - Pyodbc - Previous SQL was not a query 【发布时间】:2011-12-06 22:02:21 【问题描述】:

我无法弄清楚以下代码有什么问题, 语法没问题(用 SQL Management Studio 检查),我可以访问,所以它也可以工作。但由于某种原因,一旦我尝试通过 PyODBC 创建表,它就会停止工作。

import pyodbc

def SQL(QUERY, target = '...', DB = '...'):
    cnxn = pyodbc.connect('DRIVER=SQL Server;SERVER=' + target + DB+';UID=user;PWD=pass')
    cursor = cnxn.cursor()
    cursor.execute(QUERY)
    cpn = []

    for row in cursor:
        cpn.append(row)
    return cpn

print SQL("CREATE TABLE dbo.Approvals (ID SMALLINT NOT NULL IDENTITY PRIMARY KEY, HostName char(120));")

它失败了:

Traceback (most recent call last):
  File "test_sql.py", line 25, in <module>
    print SQL("CREATE TABLE dbo.Approvals (ID SMALLINT NOT NULL IDENTITY PRIMARY KEY, HostName char(120));")
  File "test_sql.py", line 20, in SQL
    for row in cursor:
pyodbc.ProgrammingError: No results.  Previous SQL was not a query.

有人知道这是为什么吗? 我安装了“SQL Server”驱动程序(它是默认的),在 Windows 2008 SQL Server 环境(不是快速数据库)上运行 Windows 7。

【问题讨论】:

也用“SQL Server Native Client 10.0”测试过,同样的问题..它只是说我的“以前的 SQL 不是查询”.. 另外请注意,我可以连接到服务器,一切正常(Windows 登录和 SQL 帐户登录,但无论我使用什么选项,错误都是一样的) 这是否与我使用的是企业集群并连接到集群而不是实际机器本身这一事实有关? 很明显,您正在执行的 SQL 语句不是查询!没有 SELECT 语句。如果您想找回一些东西,请CREATE TABLE ... SELECT 1 我收到此错误是因为我使用了一个执行多项操作的存储过程,其中只有一项选择了我想要的结果。 This answer 解释了如何解决这个问题。 【参考方案1】:

以防万一一些孤独的网络游民遇到这个问题,Torxed 的解决方案对我不起作用。但以下对我有用。

我正在调用一个 SP,它将一些值插入到一个表中,然后返回一些数据。只需将以下内容添加到 SP 中:

SET NOCOUNT ON

它会工作得很好:)

Python 代码:

    query = "exec dbo.get_process_id " + str(provider_id) + ", 0"
    cursor.execute(query)

    row = cursor.fetchone()
    process_id = row[0]

SP:

USE [DBNAME]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[GET_PROCESS_ID](
    @PROVIDER_ID INT,
    @PROCESS_ID INT OUTPUT
)
AS
BEGIN
    SET NOCOUNT ON
    INSERT INTO processes(provider_id) values(@PROVIDER_ID)
    SET @PROCESS_ID= SCOPE_IDENTITY()
    SELECT @PROCESS_ID AS PROCESS_ID
END

【讨论】:

添加一些额外的解决方案总是很好! 这是正确答案。如果您不想或无法更改您的过程,请使用: noCount = """ SET NOCOUNT ON; """ 然后 cursor.execute(nocount + query) 感谢您的解决方案。只是在这个答案中添加更多内容。如果你有一个 SQL 函数(而不是存储过程),SQL server 不允许你在函数中写 SET NOCOUNT ON,但是你可以在执行函数之前添加这个语句。这将有助于消除 SQL FUNCTIONS 上的“Previous SQL was not a query”。 Python 3.7 + MS SQL 2016:NOCOUNT 技巧对我不起作用(((( 2020 年仍然有效。遵循@felbus 的建议,将其作为前缀添加到查询中。【参考方案2】:

使用脚本顶部的“SET NOCOUNT ON”值并不总是足以解决问题。

在我的情况下,也有必要删除这一行:

Use DatabaseName;

数据库是 SQL Server 2012, 蟒蛇3.7, SQL 炼金术 1.3.8

希望这对某人有所帮助。

【讨论】:

谢谢,正是我需要的。 再次感谢您。我已经需要这个两次了。 :)【参考方案3】:

我得到这个是因为我正在重用一个我正在循环的游标:

rows = cursor.execute(...)
for row in rows:
    # run query that returns nothing
    cursor.execute(...)
    # next iteration of this loop will throw 'Previous SQL' error when it tries to fetch next row because we re-used the cursor with a query that returned nothing

改为使用 2 个不同的光标

rows = cursor1.execute(...)
for row in rows:
    cursor2.execute(...)

或者在再次使用之前获取第一个游标的所有结果:

改为使用 2 个不同的光标

rows = cursor.execute(...)
for row in list(rows):
    cursor.execute(...)

【讨论】:

【参考方案4】:

正如其他人所述,SET NOCOUNT ON 将处理存储过程中的额外结果集,但其他事情也可能导致 NOCOUNT 无法阻止的额外输出(并且 pyodbc 将视为结果集),例如忘记删除打印调试存储过程后的语句。

【讨论】:

【参考方案5】:

正如 Travis 和其他人所提到的,其他事情也可能导致 SET NOCOUNT ON 不会阻止的额外输出。

我在程序开始时设置了 NOCOUNT ON,但在我的结果集中收到警告消息。

我在脚本开头设置了 ansi 警告以删除错误消息。

SET ANSI_WARNINGS OFF

希望这对某人有所帮助。

【讨论】:

它帮助了我!谢谢!【参考方案6】:

如果您的存储过程调用 RAISERROR,pyodbc 可能会为该消息创建一个集合。

CREATE PROCEDURE some_sp
AS
BEGIN
    RAISERROR ('Some error!', 1, 1) WITH NOWAIT
    RETURN 777
END

在 python 中,您需要跳过第一组,直到找到包含一些结果的一组(详见https://github.com/mkleehammer/pyodbc/issues/673#issuecomment-631206107)。

sql = """
    SET NOCOUNT ON;
    SET ANSI_WARNINGS OFF;
    DECLARE @ret int;
    EXEC @ret = some_sp;
    SELECT @ret as ret;
    """
cursor = con.cursor()
cursor.execute(sql)

rows = None
#this section will only return the last result from the query
while cursor.nextset():
    try:
        rows = cursor.fetchall()
    except Exception as e:
        print("Skipping non rs message: ".format(e))
    continue

row = rows[0]
print(row[0])  # 777.

【讨论】:

【参考方案7】:

如果您的 SQL 不是存储过程。

在查询中使用 'xyz != NULL' 会产生相同的错误,即“pyodbc.ProgrammingError: No results. Previous SQL is not a query。”

改用“不为空”。

【讨论】:

【参考方案8】:

首先:

如果您运行的是 Windows SQL Server 2008,请使用 SQL 软件安装中包含的“本机客户端”(它随数据库和工具包一起安装,因此您需要安装 Microsoft 的 SQL 管理应用程序)

其次: 在您的 SQL 连接语句中使用 "Trusted_Connection=yes"

cnxn = pyodbc.connect('DRIVER=SQL Server Native Client 10.0;SERVER=ServerAddress;DATABASE=my_db;Trusted_Connection=yes')

这应该可以解决问题!

【讨论】:

【参考方案9】:

我已经通过将 use databasesql query 拆分为两个执行语句解决了这个问题。

【讨论】:

以上是关于MSSQL2008 - Pyodbc - 以前的 SQL 不是查询的主要内容,如果未能解决你的问题,请参考以下文章

pyodbc连接MSSQL执行SQL语句

Django 1.11.7+django_pyodbc_azure-1.11.0.0+pyodbc 连接mssql 数据库

python ubuntu使用pyodbc连接到mssql服务器

使用 sqlalchemy.engine.url.URL 为 mssql+pyodbc 构建连接 URL

Django With MSSQL using Pyodbc:未保存模型表单

数据未插入 MSSQL Python