pandas / sqlalchemy / pyodbc: объект результата не возвращает строки из сохраненной процедуры, когда оператор UPDATE появляется перед SELECT

Я использую SQL Server 2014, pandas 0.23.4, sqlalchemy 1.2.11, pyodbc 4.0.24 и Python 3.7.0. У меня есть очень простая хранимая процедура, которая выполняет UPDATE для таблицы, а затем SELECT для нее:

CREATE PROCEDURE my_proc_1
    @v2     INT
AS
BEGIN
    UPDATE my_table_1 
    SET v2 = @v2 
    ;

    SELECT * from my_table_1
    ;
END 
GO

Это отлично работает в MS SQL Server Management Studio. Однако, когда я пытаюсь вызвать его через Python, используя этот код:

import pandas as pd
from sqlalchemy import create_engine

if __name__ == "__main__":
    conn_str = 'mssql+pyodbc://@MODEL_TESTING'
    engine = create_engine(conn_str)
    with engine.connect() as conn:
        df = pd.read_sql_query("EXEC my_proc_1 33", conn)
        print(df)

Я получаю следующую ошибку:

sqlalchemy.exc.ResourceClosedError: этот объект результата не возвращает строки. Он был закрыт автоматически.

(Пожалуйста, дайте мне знать, если вам нужна полная трассировка стека, я обновлю, если да)

Когда я удаляю UPDATE из сохраненной процедуры, код запускается и возвращаются результаты. Также обратите внимание, что выбор из таблицы, отличной от обновляемой, не имеет значения, я получаю ту же ошибку. Любая помощь горячо приветствуется.


person sparc_spread    schedule 17.12.2018    source источник
comment
Добавьте оператор SET NOCOUNT ON; в начало хранимой процедуры и посмотрите, поможет ли это.   -  person Gord Thompson    schedule 17.12.2018
comment
Это сработало в моем тестовом примере! Сейчас тестирую с реальным кодом. Пожалуйста, не стесняйтесь публиковать это как ответ - если он работает с реальным кодом, я с радостью приму его!   -  person sparc_spread    schedule 17.12.2018


Ответы (1)


Проблема в том, что оператор UPDATE возвращает количество строк, которое является скалярным значением, а строки, возвращаемые оператором SELECT, «застревают» за счетчиком строк, где pyodbc не может их «видеть» (без дополнительных махинаций).

Считается наилучшей практикой обеспечить, чтобы наши хранимые процедуры всегда начинались с оператора SET NOCOUNT ON;, чтобы подавить возврат значений счетчика строк из операторов DML (UPDATE, DELETE и т. Д.) И позволить хранимой процедуре просто возвращать строки из оператора SELECT. утверждение.

person Gord Thompson    schedule 17.12.2018