Выполнение хранимой процедуры Oracle, возвращающей REF CURSOR, с использованием SqlAlchemy

У меня есть хранимая процедура, которую я определил в Oracle. В этой процедуре мне нужно вернуть набор записей. Для этого я использую SYS_REFCURSOR, который отлично работает внутри Oracle (и с cx_Oracle, если уж на то пошло). В моем приложении я использую сеансы с областью действия SqlAlchemy для поддержки многопоточности.

Как я могу использовать сеанс с ограниченной областью действия, чтобы вернуть REF CURSOR? Единственный способ, которым я смог заставить это работать, — это объявить курсор вывода с курсором, который активен в сеансе, а затем выполнить хранимую процедуру, как показано ниже:

sql = """
    BEGIN
        example('%s', '%s', '%s', :cur);
    END;
""" % (cid, show, type)

conn = sa_tool.session.connection()
in_cur = conn._Connection__connection.cursor()
out_cur = conn._Connection__connection.cursor()
in_cur.execute(sql, cur=out_cur)
results = out_cur.fetchall()

В идеале я хотел бы избежать использования объекта подключения таким образом и выполнять процедуру, позволяя SqlAlchemy управлять курсорами. Если это невозможно, есть ли причина, по которой выборка займет так много времени?

Спасибо


person zmouser    schedule 05.12.2011    source источник
comment
Ну, медлительность, конечно, моя вина, и плохой запрос в хранимой процедуре. Остается вопрос: есть ли лучший способ вызвать хранимую процедуру в SqlAlchemy, используя Oracle REF CURSOR?   -  person zmouser    schedule 06.12.2011


Ответы (1)


Я увидел этот вопрос, на который не ответили, и решил вмешаться. Прежде всего, позвольте мне просто сказать, что для вашего сценария нет лучшего варианта, чем SYS_REFCURSOR. Конечно, у вас есть альтернативы.

Курсор Oracle — это область памяти, в которой хранится инструкция по выполнению оператора SQL. Курсор Ref — это просто указатель на местоположение курсора. SYS_REFCURSOR — это конкретный оракул, определенный типом курсора ref. Таким образом, когда вы возвращаете переменную SYS_REFCURSOR клиенту, вы возвращаете указатель на область памяти, где находится инструкция для выполнения SQL. Теперь ваш клиент может выполнить инструкцию с помощью операции FETCH и получить строки. Так что это наилучший способ вернуть результирующий набор клиенту.

В качестве альтернативы вы можете использовать КОНВЕЙЕРНУЮ ФУНКЦИЮ, но я могу заверить вас, что вы не получите лучшей производительности. У AskTom есть отличное объяснение этого сравнения в этой статье.

https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:9532870400346178516

Другой сценарий заключается в том, хотите ли вы проанализировать, где потребляется время, либо на этапе EXECUTE, либо на этапе FETCH. Если у вас много времени в FETCH, возможно, вы могли бы рассмотреть возможность передачи данных клиенту другим способом. Если у вас есть проблемы с ВЫПОЛНЕНИЕМ, вам нужно выполнить упражнение по настройке вашей процедуры.

person Roberto Hernandez    schedule 26.07.2020