使用 SqlAlchemy 执行返回 REF CURSOR 的 Oracle 存储过程

Posted

技术标签:

【中文标题】使用 SqlAlchemy 执行返回 REF CURSOR 的 Oracle 存储过程【英文标题】:Executing an Oracle stored procedure returning a REF CURSOR using SqlAlchemy 【发布时间】:2012-01-13 11:34:49 【问题描述】:

我有一个在 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 管理游标的同时执行该过程。如果这不可能,是否有原因导致提取需要这么长时间?

谢谢

【问题讨论】:

嗯,速度慢肯定是我自己的错,而且是存储过程中的错误查询。问题仍然存在,有没有更好的方法在 SqlAlchemy 中调用存储过程,使用 Oracle REF CURSOR 【参考方案1】:

我看到了这个没有回答的问题,我决定加入。首先,我只想说,对于您的场景,没有比 SYS_REFCURSOR 更好的选择。当然,您还有其他选择。

Oracle 游标是存储执行 SQL 语句的指令的内存区域位置。 Ref 光标只是指向光标位置的指针。 SYS_REFCURSOR 是一个特定的 oracle 定义类型的 ref 游标。因此,当您将 SYS_REFCURSOR 变量返回给客户端时,您将返回一个指向执行 SQL 的指令所在的内存位置的指针。您的客户端现在可以使用 FETCH 操作执行指令并获取行。所以这是向客户端返回结果集的最佳方式。

作为替代方案,您可以使用 PIPELINED FUNCTION,但我可以向您保证,您不会获得更好的性能。 AskTom 在这篇文章中对这种比较有很好的解释

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

另一种情况是您是否要分析时间消耗在哪里,无论是在 EXECUTE 阶段还是在 FETCH 阶段。如果您在 FETCH 中花费大量时间,也许您可​​以考虑以另一种方式将数据传输到客户端。如果您在执行中遇到问题,那么您需要对您的过程进行调整练习。

【讨论】:

以上是关于使用 SqlAlchemy 执行返回 REF CURSOR 的 Oracle 存储过程的主要内容,如果未能解决你的问题,请参考以下文章

如何返回sqlalchemy执行的SQL语句及其所花时间

SQLAlchemy 查询返回无

uploadTask 成功后,ref.downloadURL() 不执行或返回 url

sqlalchemy 在多个列中是唯一的

SQLAlchemy 中的查询查找

Scrapy - SQLite 中未创建 SQLalchemy 外键