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

Tor*_*xed 27 python windows pyodbc sql-server-2008

我无法弄清楚以下代码有什么问题,语法是正确的(使用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));")
Run Code Online (Sandbox Code Playgroud)

它失败了:

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.
Run Code Online (Sandbox Code Playgroud)

任何人都知道为什么会这样?我安装了一个"SQL Server"驱动程序(这是默认设置),针对Windows 2008 SQL Server环境(非快速数据库)运行Windows 7.

tex*_*ens 59

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

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

SET NOCOUNT ON
Run Code Online (Sandbox Code Playgroud)

它会工作得很好:)

Python代码:

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

    row = cursor.fetchone()
    process_id = row[0]
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案.如果你不想,或者不能改变你的程序,那么使用:noCount ="""SET NOCOUNT ON;"""然后cursor.execute(nocount + query) (15认同)
  • Python 3.7 + MS SQL 2016:NOCOUNT 的技巧对我不起作用(((( (3认同)

Tom*_*ish 9

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

就我而言,还需要删除此行:

Use DatabaseName;
Run Code Online (Sandbox Code Playgroud)

数据库为 SQL Server 2012、Python 3.7、SQL Alchemy 1.3.8

希望这可以帮助某人。

  • 谢谢,正是我需要的。 (2认同)

Mat*_*att 8

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

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
Run Code Online (Sandbox Code Playgroud)

改用 2 个不同的光标

rows = cursor1.execute(...)
for row in rows:
    cursor2.execute(...)
Run Code Online (Sandbox Code Playgroud)

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

改用 2 个不同的光标

rows = cursor.execute(...)
for row in list(rows):
    cursor.execute(...)
Run Code Online (Sandbox Code Playgroud)


小智 5

正如其他人介绍的那样,SET NOCOUNT ON将处理存储过程中的额外结果集,但是其他事情也可能导致 NOCOUNT 不会阻止的额外输出(并且 pyodbc 将视为结果集),例如在调试存储过程后忘记删除打印语句.


小智 5

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

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

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

SET ANSI_WARNINGS OFF
Run Code Online (Sandbox Code Playgroud)

希望这对某人有帮助。