MSSQL2014 & python 3.7.3: Попытка получить возвращаемое значение хранимой процедуры приводит к «Нет результатов. Предыдущий SQL не был запросом». - PullRequest
2 голосов
/ 28 апреля 2020

Я запускаю сценарий python, который подключается к базе данных MS SQL, выполняет хранимую процедуру и должен предпринять некоторые действия в зависимости от возвращаемого значения хранимой процедуры. Вот код:

'''
sql = """\
        SET NOCOUNT ON
        DECLARE @rv INT
        EXEC @rv = [MY_DB].[dbo].[sp_Load_Actuals]
        SELECT @rv 
        """
...
conn = pyodbc.connect('Driver={ODBC Driver 13 for SQL Server};'
                                      'Server=MY_SERVER;'
                                      'Database=MY_DB;'
                                      'Trusted_Connection=yes;')

conn.autocommit = True
cursor = conn.cursor()
cursor.execute(sql)
retv = cursor.fetchone() 
...

При выполнении последнего оператора я ловлю исключение pyodb c .DatabaseError с сообщением "Нет результатов . Предыдущий SQL не был запросом. " Я прочитал все связанные статьи здесь, но, видимо, я все еще делаю что-то не так.

Что мне не хватает?

1 Ответ

2 голосов
/ 02 мая 2020

Вы должны позвонить cursor.nextset(), чтобы пропустить любые информационные сообщения, которые были выведены вызванными хранимыми процедурами, так как NOCOUNT ON здесь недостаточно.

Но, к сожалению, cursor не имеет метода .hasrows(), поэтому вы должны поймать исключение в al oop.

EG:

import pyodbc


sql = """\
        SET NOCOUNT ON
        DECLARE @rv INT
        EXEC @rv = sp_executesql N'print ''informational message'''
        SELECT @rv 
        """

conn = pyodbc.connect('Driver={ODBC Driver 17 for SQL Server};'
                                      'Server=localhost;'
                                      'Database=tempdb;'
                                      'Trusted_Connection=yes;')

conn.autocommit = True
cursor = conn.cursor()
cursor.execute(sql)

while True:
    try:
        retv = cursor.fetchone() 
        break
    except pyodbc.ProgrammingError as e:
       if "Previous SQL was not a query." in str(e):
        if not cursor.nextset():
          throw

print(retv)
...