【问题标题】:PL/SQL: How to create type from cursorPL/SQL:如何从游标创建类型
【发布时间】:2014-08-22 13:05:55
【问题描述】:

我可以从光标定义类型吗?

目前我必须编写以下内容才能从某些表字段创建记录变量:

declare

    cursor cur
    is
        select 
            f_1,
            f_2,
            f_3,
            f_4
        from
            mytable
        where 
            1=0;

    myvar cur%rowtype;              -- use the cursor to declare myvar

begin
    null;
end;

我想写这样的东西:

declare

    cursor cur
    is
        select 
            f_1,
            f_2,
            f_3,
            f_4
        from
            mytable
        where 
            1=0;

    type mytype is cur%rowtype;     -- declare "mytype" from cursor
    myvar mytype;                   -- use "mytype" to declare "myvar"

begin
    null;
end;

这在这个琐碎的例子中看起来没有用,但在实际问题中可能很有用。

另一种方法是手动创建记录类型:

declare

    type mytype is record           -- declare "mytype"
    (
        f_1    mytable.f_1%type,
        f_2    mytable.f_2%type,
        f_3    mytable.f_3%type,
        f_4    mytable.f_4%type
    );
    myvar mytype;                   -- use "mytype" to declare "myvar"

begin
    null;
end;

但这对我来说更脏(我必须重复每个字段名两次,并且多次重复表名)。

【问题讨论】:

    标签: oracle types plsql record


    【解决方案1】:

    我可以从光标定义类型吗?

    是的,您可以使用subtype 关键字而不是type 关键字来定义您自己的基于cursor_name%rowtype 记录类型的类型(基本上在这种情况下它将是同义词)。

    这是一个例子:

    set serveroutput on;
    declare
      cursor c1 is
        select 1 as col1
             , 2 as col2
             , 3 as col3
         from dual;
    
      subtype mytype is c1%rowtype;
      l_myvar mytype;
    begin
      open c1;
      fetch c1 into l_myvar;
      dbms_output.put(to_char(l_myvar.col1) || ' : ');
      dbms_output.put(to_char(l_myvar.col2) || ' : ');
      dbms_output.put_line(to_char(l_myvar.col3));
      close c1;
    end;
    

    结果:

    anonymous block completed
    
    1 : 2 : 3
    

    【讨论】:

      【解决方案2】:

      我认为你在这里要做的是使用一个ROWTYPE变量,如下:

      DECLARE
        CURSOR c1 IS
          SELECT t.COL1, t.COL2, t.COL3
            FROM MY_TABLE t
            WHERE t.ADD_DATE >= TRUNC(SYSDATE, 'MONTH');
      
        c1Row  c1%ROWTYPE;
      BEGIN
        OPEN c1;
      
        LOOP
          FETCH c1 INTO c1Row;
          EXIT WHEN c1%NOTFOUND;
      
          DBMS_OUTPUT.PUT_LINE('COL1=' || c1Row.COL1 ||
                               '  COL2=' || c1Row.COL2 ||
                               '  COL3=' || c1Row.COL3);
        END LOOP;
      
        CLOSE c1;
      END;
      

      Reference here

      分享和享受。

      【讨论】: