return 来自用户 table 记录的所有值

return all values from user table record

比方说,我有一个名为 get_prod 的过程,它 returns 一个用户定义的记录:

create or replace package test is
    cursor cGetProducts(NROWS integer) is
        select prod.PROD_REF,
               prod.PROD_IDENT,
               prod.PROD_DESCR,
               prod.PROD_GENDATE,
               prod.PROD_GENUSERNO,
               pu.PU_LENGTH,
               pu.PU_WIDTH,
               pu.PU_HEIGHT,
               pu.PU_WEIGHT
          from product    prod,
               product_um pu
         where prod.PROD_REF = pu.PROD_REF
           and prod.PROD_UMBASE = pu.PU_UM
           and rownum <= NROWS;

    type rec_tt is record(
        prod_ref integer,
        prod_ident varchar(50),
        PROD_DESCR varchar(100),
        prod_gendate date,
        prod_genuser integer,
        prod_length number(21,6),
        prod_width number(21,6),
        prod_height number(21,6),
        prod_weight number(21,6)
    );

    type prod_t is table of rec_tt index by BINARY_INTEGER;
    
    procedure get_prod(
        MAXROWS             in      integer,
        NROWS               in      integer,
        o_table                 out prod_t
    );
end test;
/
create or replace package body test is
    procedure get_prod(
        MAXROWS             in      integer,
        NROWS               in      integer,
        o_table                 out prod_t
    )is
    begin
        if not cGetProducts%isOpen then
            open cGetProducts(NROWS);
        end if;

        fetch cGetProducts
         bulk collect into o_table;

        if cGetProducts%NotFound or MAXROWS>0 and cGetProducts%RowCount>MAXROWS then
            close cGetProducts;
        end if;
    end get_prod;
end test;
/

测试这个程序没什么大不了的,但要查看 table 的结果,我不得不遍历 table 并记下记录中的每个参数,例如那:

declare
    -- Non-scalar parameters require additional processing 
    o_table TEST.PROD_T;
begin
    -- Call the procedure
    test.get_prod(
        MAXROWS => 0,
        NROWS   => 99,
        o_table => o_table);
    
    for i in 1..o_table.count loop
        dbms_output.put_line(o_table(i).prod_ref);
        dbms_output.put_line(o_table(i).prod_ident);
        ...
        ...
    end loop;
end;

但我会记下记录的每个参数并获取它。有没有更简单的方法来做到这一点,尤其是当记录的参数更多时?

您可以使用数据库定义的自定义类型。这些类型可以有自己的方法,所以你可以只实现一个输出方法。

下面是我的意思的例子:

create or replace type VarcharArray_T as
table of varchar2(32767 char);


create or replace type VarcharArrayObj_T force as object
(
  -- Attributes
  Value                VarcharArray_T,
    
  -- Constructor
  constructor function VarcharArrayObj_T return self as result,
  
  -- Methods
  member procedure Output
)

create or replace type body VarcharArrayObj_T is
  
  --
  -- Constructor 
  --
  constructor function VarcharArrayObj_T
  return self as result 
  is
  begin
  
    self.Value := VarchArarray_T();
    
    return;
  end;
  
  --
  --  Prints the values to console
  --
  member procedure Output
  is
    i                             number := 0;
  begin
    i := self.Value.First();
    
    while i is not null
    loop
      -- !!! You can implement the child attribute access here once !!!
      DBMS_Output.Put_Line(self.Value(i)); 
      
      i := self.Value.Next(i);         
    end loop;
  end;
  
end;