Oracle PL SQL ref cursor%ROWTYPE 此表达式的类型声明不完整或格式错误

Posted

技术标签:

【中文标题】Oracle PL SQL ref cursor%ROWTYPE 此表达式的类型声明不完整或格式错误【英文标题】:Oracle PLSQL refcursor%ROWTYPE the declaration of the type of this expression is incomplete or malformed 【发布时间】:2019-06-17 09:41:53 【问题描述】:

我想在 PL/SQL 代码中分配游标变量,然后从中获取一行。当我明确声明游标时,它可以工作。

DECLARE
cursor c1 is SELECT * from acme;
row1 c1%ROWTYPE;

但是当我使用代码来分配光标时,例如Oracle PLSQL setting a cursor from a variable 这样:

  c1 sys_refcursor;
  r1 c1%ROWTYPE;

我得到错误

此表达式的类型声明不完整或 格式错误

只写r1 %ROWTYPE 也会产生错误。

根据变量的一般用途解释,例如这里How to declare variable and use it in the same Oracle SQL script?我试过了:

SET SERVEROUTPUT ON
DECLARE
  c1 sys_refcursor;
BEGIN
    open c1 for 'SELECT * FROM foo';
    declare r1 c1%ROWTYPE;
    begin
        fetch c1 into r1; 
    end;
    DBMS_OUTPUT.PUT_LINE('FOO');    
    close c1;
END;

又得到the declaration of the type of this expression is incomplete or malformed

我该如何声明行类型的变量呢?甲骨文 11g. 附:解决方法是 fetch c1 into v_empno, v_ename, ect 声明几个变量,还有没有办法使用 rowtype one?

【问题讨论】:

简短答案 - sys_refcursor 没有定义任何列,因此它没有 %rowtype,并且在编译时也没有动态引用光标。 @William Robertson,谢谢。我已经实施了某种解决方法,因为我的查询仍然不同。 【参考方案1】:

这样的?

SQL> set serveroutput on
SQL>
SQL> declare
  2    c1 sys_refcursor;
  3    r1 dept%rowtype;                      --> this
  4  begin
  5    open c1 for 'select * from dept';
  6    fetch c1 into r1;
  7    dbms_output.put_line(r1.dname);
  8  end;
  9  /
ACCOUNTING

PL/SQL procedure successfully completed.

SQL>

【讨论】:

我想使用 refcursor 变量的原因是我在循环中为它分配了不同的选择,使用连接和外部数据库链接进行选择。 据我所知,你不能那样做;您必须将每个引用游标的列提取到其自己的变量中。【参考方案2】:

如果您打算显示任何给定查询的结果,您可以使用类似于this AskTOM article 中描述的标准过程

create or replace procedure return_result( l_query varchar2 )
   is
       l_theCursor     integer default dbms_sql.open_cursor;
       l_columnValue   varchar2(4000);
       l_status        integer;
       l_colCnt        number := 0;
       l_separator     varchar2(1);
       l_descTbl       dbms_sql.desc_tab;
   begin
       dbms_sql.parse(  l_theCursor,  l_query, dbms_sql.native );

       dbms_sql.describe_columns( l_theCursor, l_colCnt, l_descTbl );


           l_separator := '';
           for i in 1 .. l_colCnt loop
               dbms_output.put( l_separator || l_descTbl(i).col_name );
               l_separator := ',';
           end loop;
           dbms_output.put_line('');

        for i in 1 .. l_colCnt loop
           dbms_sql.define_column( l_theCursor, i, l_columnValue, 4000 );
       end loop;
       l_status := dbms_sql.execute(l_theCursor);

       while ( dbms_sql.fetch_rows(l_theCursor) > 0 ) loop
           l_separator := '';
           for i in 1 .. l_colCnt loop
               dbms_sql.column_value( l_theCursor, i, l_columnValue );
               dbms_output.put( l_separator || l_columnValue );
               l_separator := ',';
           end loop;
           dbms_output.new_line;
       end loop;
       dbms_sql.close_cursor(l_theCursor);
   end;
 /

将任何查询传递给此过程以获得结果。

set serveroutput on
set feedback off
set sqlformat ansiconsole
set pages 0
BEGIN
return_result('select e.employee_id,e.first_name,e.salary,
          d.department_name from 
          employees e join 
  departments d on e.department_id= d.department_id');
END;
/

结果

EMPLOYEE_ID,FIRST_NAME,SALARY,DEPARTMENT_NAME
200,Jennifer,4400,Administration
201,Michael,13000,Marketing
202,Pat,6000,Marketing
114,Den,11000,Purchasing

注意:Oracle 12c 提供了DBMS_SQL.RETURN_RESULT,使用它可以轻松实现此过程。

【讨论】:

以上是关于Oracle PL SQL ref cursor%ROWTYPE 此表达式的类型声明不完整或格式错误的主要内容,如果未能解决你的问题,请参考以下文章

空 Oracle REF CURSOR 中的列名

Oracle PL/SQL:如何从 VARRAY 的 REF 中进行 DEREF?

oracle PL/SQL编程语言之游标的使用

oracle PL/SQL编程语言之游标的使用

PL/SQL练习游标cursor :oracle 在执行sql语句时,为sql语句所分配的一个私有的内存区域

oracle cursor 用法总结