7
CREATE OR REPLACE TYPE ty_1 AS OBJECT ( fn VARCHAR2(100),
                                        sl NUMBER,
                                        hd DATE );
CREATE OR REPLACE TYPE ty_1_table AS TABLE OF ty_1;

CREATE OR REPLACE FUNCTION FN_RET_COL
  RETURN ty_1_table
AS
  c ty_1_table := TY_1_TABLE();
  BEGIN
    c.extend;
    C(1) := TY_1('A', 1, '10-JUN-2013');
    c.extend;
    C(2) := TY_1('B', 2, '11-JUN-2013');
    c.extend;
    C(3) := TY_1('C', 3, '12-JUN-2013');

    RETURN c;
  END;

CREATE OR REPLACE FUNCTION FN_RET_PIPE RETURN ty_1_table PIPELINED IS
  BEGIN
    PIPE ROW (TY_1('A', 1, '10-JUN-2013'));
    PIPE ROW (TY_1('B', 2, '11-JUN-2013'));
    PIPE ROW (TY_1('C', 3, '12-JUN-2013'));
  END;

SELECT * FROM TABLE (fn_ret_col);

SELECT * FROM TABLE (fn_ret_pipe);

第一个FN_RET_COL是常规表函数,第二个FN_RET_PIPE是流水线函数。我在一本书中学习了常规表函数要求集合在返回之前完全填充,因为在创建行后PIPELINED FUNCTION 使用PIPE ROW调用将行从函数中推出,而不是建立表集合。节省内存并允许在生成所有行之前开始后续处理。我的疑问是:如何PIPELINED Function节省内存?如果我没记错的话,它将所有行都管道化并将它们存储在内存区域中,然后在控制台中打印所有行。还是像这样,只要在控制台中通过管道传输新记录而不将其存储在任何地方,它就会直接逐行打印?

CREATE OR REPLACE FUNCTION FN_RET_COL RETURN TY_1_TABLE
 PIPELINED IS
 BEGIN   
    PIPE ROW(TY_1('A',1,'10-JUN-2013'));
    DBMS_LOCK.sleep(seconds => 10);
    PIPE ROW(TY_1('B',2,'11-JUN-2013'));
    DBMS_LOCK.sleep(seconds => 10);
    PIPE ROW(TY_1('C',3,'12-JUN-2013'));
 END;

如果我的第二种情况是正确的,那么上面的代码是如何工作的?

4

1 回答 1

11

Pipelined函数,一个非常经典的例子是你SELECT * FROM table nameSQL*Plus. 发生的事情是,Oracle 从表中流式传输数据..

就像在 youtube 上观看视频一样。

请注意“式传输”这个词。在我们的函数中,我们定义了流式传输的行数。每个流式传输的行都立即可供调用者使用。Pipelining用外行的话来说,不要让我等到你完成,把你所有的都给我,同时继续处理和更新我。

在您的最后一个过程中,在对每一行进行管道传输之后,您发起一个对 的sleep调用10s,因此该记录每 10 秒被流式传输给调用者。

并且,一个普通的表函数会一直等待,直到所有处理工作完成,然后它会返回对结果集游标的引用。

他们声称可以节省内存的流水线函数是flushing立即按内容处理的,因此使用的缓冲区总是最小的,而往返次数会更高。

于 2014-01-16T20:26:53.010 回答