MSSQL2008 - Pyodbc - предыдущий SQL не был запросом - PullRequest
22 голосов
/ 13 октября 2011

Я не могу понять, что не так с приведенным ниже кодом. Синтаксис работает нормально (проверено в 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 7 в среде Windows Server SQL Server (не в базе данных Express).

Ответы [ 5 ]

52 голосов
/ 20 февраля 2013

На случай, если какой-нибудь одинокий сетевой кочевник столкнется с этой проблемой, решение 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]

ИП:

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
3 голосов
/ 08 августа 2016

Я получил это, потому что я повторно использовал курсор, над которым я зацикливался:

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(...)
2 голосов
/ 09 ноября 2017

Как уже говорилось, SET NOCOUNT ON позаботится о дополнительных наборах результатов внутри хранимой процедуры, однако другие вещи могут также вызвать дополнительный вывод, который NOCOUNT не будет предотвращать (и pyodbc будет видеть как набор результатов), например, забыв удалить печать заявление после отладки вашей хранимой процедуры.

0 голосов
/ 16 января 2014

В случае, если ваш SQL не является сохраненным процессом.

Использование в запросе 'xyz! = NULL' приведет к той же ошибке, например "pyodbc.ProgrammingError: Результатов нет. Предыдущий SQL не был запросом."

Вместо этого используйте 'not null'.

0 голосов
/ 25 октября 2011

Прежде всего:

, если вы используете Windows SQL Server 2008, используйте «собственный клиент», который входит в комплект установки программного обеспечения SQL (он устанавливается вместе с базой данных и наборами инструментов, поэтому вынеобходимо установить приложение SQL Management от Microsoft)

Во-вторых: используйте "Trusted_Connection = yes" в своем операторе соединения SQL:

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

Это должно сработать!

...