【问题标题】:Is using a SELECT inside a pipelined PL/SQL table function allowed?是否允许在流水线 PL/SQL 表函数中使用 SELECT?
【发布时间】:2010-12-08 12:31:30
【问题描述】:

流水线函数的文档说 DML 在 SQL 语句中使用时是不允许的(通常是 SELECT),并且在大多数示例中,流水线函数用于数据生成或转换(接受 custor 作为参数),但不发出任何 DML 语句。

现在,从技术上讲,可以使用 SELECTs 而不会出现来自 Oracle 的任何错误(ORA 14551 不会发生)。但是,我遇到了可重现的选择奇怪行为;即使PRAGMA AUTONOMOUS_TRANSACTION 没有被使用,SELECT 检索到的行似乎总是考虑到当前的本地事务,这对我来说就像一个错误.更令人不安的是,当使用分布式事务(例如通过 ORAMTS 而不是本地事务)时,会使用事务。

编辑: 事实证明,奇怪的效果似乎与查询中的某些 WITH 语句有关,这些语句有时有效,有时无效(取决于 Oracle 优化器的当前情绪,至少在10 克)。在某些情况下,我得到一个 ORA-32036,然后它又没有发生,根本没有更改代码。现在看起来,有时使用 ORA-32036 失败的查询似乎也未能使用正确的事务,并且可能与流水线功能无关。

所以我的具体问题是:

  • 是否有任何(最好是官方的)声明是否允许流水线表函数中的SELECTs 以​​及它们的事务上下文是什么?

  • 是否有另一种模块化常用查询的方法,可以在 SQL 语句中使用(就像表函数可以使用 TABLE())?

  • 有没有人也经历过这种行为并且可能对此了解更多?我研究了metalink,但不幸的是我没有找到任何关于该主题的具体内容。

【问题讨论】:

    标签: sql oracle plsql dml pipelined-function


    【解决方案1】:
    1. 通常 DML 限制只涉及修改(UPDATE、DELETE ...)语句,因此 SELECT 应该没问题。我会尝试从 Oracle 中找到具体的声明。

    2. 视图将是您将常用查询模块化的第一个工具。

    3. 函数相对于视图有一个缺点:如果从另一个 SELECT 调用它们,它们不会在与主 SELECT 相同的时间点执行。对 SELECT 的每次调用都是一致的,但由于 SELECT 在函数代码中而不是在主 SQL 中,因此您可能会返回不一致的结果。这对于视图和子选择来说是不可能的:如果一个大语句调用一个视图,则视图是在与主查询相同的时间点构建的。

    更新:关于您对参数化查询的评论

    您可以构建参数化视图,即依赖于执行前设置的变量的视图。 Here is an example on AskTom 展示了如何使用 userenv('client_info')dbms_session.set_context 来做到这一点。

    【讨论】:

    • 感谢您的回复。关于 2,问题是我有在处理递归之前需要考虑的参数。事实上,我们有一个图连接的历史列表,它们有一个创建和删除日期/时间(删除的 null 表示未删除)。现在我必须重建图表,因为它在某个日期/时间,所以我目前看不到如何用视图解决这个问题。基本上,如果你了解 T-SQL,我想要一种方法来实现类似于在那里找到的内联表函数,我发现最接近的是流水线表函数。
    • 关于 3,我的问题不是由于它们被执行的时间点。我有打开连接、启动事务、插入数据(使用插入)、调用使用该函数的 SP 并显示结果的测试。这些测试失败,即使它们没有与其他任何东西同时运行,即使在发生这种情况的情况下,这些函数也足够粗略并且在单个语句中执行查询(带有多个 WITH),因此结果应该是持续的。但是感谢您指出这一点。
    • @Lucero:我更新了关于 2 的答案。关于您对第 3 点的评论,如果您的函数不是自治事务,则它应该在同一个事务上,并且看到与您的主要查询相同的数据。但是有两个问题:1)您的流水线函数是从 INSERT 还是从另一个 SELECT 调用的? 2)如果你重写非流水线函数,你会得到同样的不一致吗?
    • @Vincent,我知道这种技术(有人告诉我,我应该更喜欢 sys_context 而不是 userenv,但基本概念是相同的)。但是,由于我有一些 6 参数,我需要传递到“参数化视图”,据我所知,它们只返回 varchars,这意味着它们必须转换为要比较的列类型(在我的情况下为 2 datetime 和 4 个 raw(16) guids),我担心这不会很有效。但是,性能非常关键。回答您的问题:仅在 SELECT 中,但从 SP 将其作为 REF CURSOR 返回。尚未尝试非流水线,将尝试。
    • @Vincent,关于非流水线,这是一个比我预期的更大的变化...... Oracle 声明“注意:返回包级别类型的表函数必须是流水线的。”在oracle.com/technology/sample_code/tech/pl_sql/htdocs/x/…
    猜你喜欢
    • 2021-07-26
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多