Oracle会跳过嵌套的PIPELINED函数

时间:2014-07-05 13:03:52

标签: oracle plsql oracle11g

我会发布一个简单的例子,它实际上是有效的,只是为了得到我想要实现的内容的近似图片:

这是'内部'函数,它从一些表中获取数据,称为test_tab

create or replace function test_inner RETURN num_typ PIPELINED
IS
BEGIN
  FOR cur in (
    SELECT x FROM test_tab
  )
  LOOP
    PIPE ROW(cur.x);
  END LOOP;
END;
/

这是'外部'函数,它使用inner函数的结果并适当地转换它们:

create or replace function test_outer RETURN num_typ PIPELINED
IS
BEGIN
  FOR x IN (
    SELECT * FROM table(test_inner())
  )
  LOOP
    PIPE ROW(x.column_value * 2);
  END LOOP;
END;
/

以下是我如何使用它:

begin
  execute immediate 'insert into test_tab(x) values(1)';
  execute immediate 'insert into test_tab(x) values(2)';
  execute immediate 'insert into test_tab(x) values(3)';

  FOR x IN (
    select * from table(test_outer())
  ) LOOP  
    DBMS_OUTPUT.put_line(x.column_value);
  END LOOP;  
end;
/

问题是Oracle似乎忽略了test_inner函数。当它被单独调用时,它会“看到”在执行之前插入的数据。但当它被称为test_outer的一部分时,它不会返回任何数据,或者根本不会被调用。

就像我说的,上面的例子会起作用。但我的情况有点复杂,所以我不能完全发布它。

2 个答案:

答案 0 :(得分:3)

您发布的测试用例不会重现您声称看到的问题。所以它不是一个测试用例。

@AlexPoole为您提供了一些其他想法。基本上没有什么可以做的,除非你能发布一个更好的测试用例,因为你不能发布所有的东西(而且我们不想通过数百行其他人的代码 - 我得到足够的调试我自己的东西)。

制作一个糟糕的测试用例并不是浪费时间。至少你可以排除某些事情:它与一个流水线函数调用另一个无关。因此,在您的具体实施中,它显然是一些东西。也许不是在内部函数逻辑中,而是它们如何被调用,它们使用的数据或基础结构的其他部分。

您所能做的就是分析各个部分。从核心组件开始,然后构建,添加其他组件,直到找到中断的位。是的,这是一项乏味的苦差事。但是从您的评论中可以看出,您已经完成了这个过程。


我标记这个CW,因为它不是问题的答案,只是一个扩展的评论。

答案 1 :(得分:-1)

您的两个流水线函数实际上都是语法错误:您缺少 RETURN

See docs