У меня есть хранимая процедура, которую я определил в 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 управлять курсорами. Если это невозможно, есть ли причина, по которой выборка займет так много времени?
Спасибо
Ответ 1 · Roberto Hernandez
Я увидел этот вопрос, на который не ответили, и решил вмешаться. Прежде всего, позвольте мне просто сказать, что для вашего сценария нет лучшего варианта, чем 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, возможно, вы могли бы рассмотреть возможность передачи данных клиенту другим способом. Если у вас есть проблемы с ВЫПОЛНЕНИЕМ, вам нужно выполнить упражнение по настройке вашей процедуры.