create or replace procedure sp_DoHouseKeeping
as
strSQL varchar2(2048);
begin
-- 声明一个游标
cursor mycursor is 
select
'alter database datafile '''||a.file_name||''' resize '
||round(a.filesize - (a.filesize - c.hwmsize-100) *0.8)||'M;' runstatement
from 
(
select file_id,file_name,round(bytes/1024/1024) filesize from dba_data_files
) a,
(
select file_id,round(max(block_id)*8/1024) HWMsize from dba_extents
group by file_id
) c
where a.file_id = c.file_id
  and a.filesize - c.hwmsize > 100;
-- 声明一个游标变量
rowdata mycursor%rowtype;
begin
-- 处理数据
for rowdata in mycursor loop
-- 构造PL/SQL语句
strSQL:=rowdata.runstatement;
-- 打印SQL语句
DBMS_OUTPUT.PUT_LINE(strSQL);
-- 执行动态SQL语句
execute immediate strSQL;
commit;
end loop;
end;
end;编译提示错误,提示MYCURSOR格式不正确。
我单独执行CURSOR IS后面的select语句是正确的啊。这是怎么回事???请帮忙看下。

解决方案 »

  1.   

    显示游标的申明,隐式游标的调用
    直接for rowdata in (select ...) loop
    rowdata也不用定义。
      

  2.   

    不对吧。如果我更改cursor myCursor is select_statement就可以通过编译了。我在其他的procedure里面已经这么使用,工作OK。应该不是你说的这个问题。百思不解,2天搞不定。
      

  3.   

    显式游标要先声明才能在执行体里调用的create or replace procedure sp_DoHouseKeeping
    as
        strSQL    varchar2(2048);
        -- 声明一个游标
        cursor mycursor is
        select
        'alter database datafile '''||a.file_name||''' resize '
        ||round(a.filesize - (a.filesize - c.hwmsize-100) *0.8)||'M;' runstatement
        from
        (
            select file_id,file_name,round(bytes/1024/1024) filesize from dba_data_files
        ) a,
        (
            select file_id,round(max(block_id)*8/1024) HWMsize from dba_extents
            group by file_id
        ) c
        where a.file_id = c.file_id
              and a.filesize - c.hwmsize > 100;
        -- 声明一个游标变量
        rowdata mycursor%rowtype;
        begin
            -- 处理数据
            for rowdata in mycursor loop
                -- 构造PL/SQL语句
                strSQL:=rowdata.runstatement;
                -- 打印SQL语句
                DBMS_OUTPUT.PUT_LINE(strSQL);
                -- 执行动态SQL语句
                execute immediate strSQL;
                commit;
            end loop;
    end;
      

  4.   

    不对吧。如果我更改cursor myCursor is select_statement就可以通过编译了。我在其他的procedure里面已经这么使用,工作OK。应该不是你说的这个问题。百思不解,2天搞不定。
    我也是百思不得其解,为什么cursor 前面要有begin呢?
      

  5.   

    不对吧。如果我更改cursor myCursor is select_statement就可以通过编译了。我在其他的procedure里面已经这么使用,工作OK。应该不是你说的这个问题。百思不解,2天搞不定。
    我以为你的游标是有变量绑定的开始,那样子才是要使用包,说错了那~
      

  6.   

    不对吧。如果我更改cursor myCursor is select_statement就可以通过编译了。我在其他的procedure里面已经这么使用,工作OK。应该不是你说的这个问题。百思不解,2天搞不定。
    那个动态sql那句话里面貌似是不用‘:’这个的...
      

  7.   

    1 变量声明要写在as   begin之间2 去掉sql里的分号。
      

  8.   

    调试了一下:发现一些问题:1. 将游标的定义写在begin前面2. 'alter database datafile '''||a.file_name||''' resize '
        ||round(a.filesize - (a.filesize - c.hwmsize-100) *0.8)||'M;' runstatement去掉'M;'里面的分号。
    3. 可以先把这个SQL取出来执行一下,看是否正确。
      

  9.   

    SQL> create or replace procedure sp_DoHouseKeeping
      2  as
      3  cursor cur1 is
      4  select a.file_name,round(a.filesize - (a.filesize - c.hwmsize-100) *0.8) runstatement
      5  from
      6      (
      7          select file_id,file_name,round(bytes/1024/1024) filesize from dba_data_files
      8      ) a,
      9      (
     10          select file_id,round(max(block_id)*8/1024) HWMsize from dba_extents
     11          group by file_id
     12      ) c
     13      where a.file_id = c.file_id
     14            and a.filesize - c.hwmsize > 100;
     15  begin
     16     null;
     17  end;
     18  /警告: 创建的过程带有编译错误。SQL>
    SQL>
    SQL>
    SQL> create or replace procedure sp_DoHouseKeeping
      2  as
      3  cursor cur1 is
      4  select * from emp;
      5  begin
      6     null;
      7  end;
      8  /过程已创建。
    你的SQL语句,oracle认为有问题,oracle自己的bug吧,你把语句写简单点
      

  10.   

    SQL> create or replace procedure sp_DoHouseKeeping
      2  as
      3  cursor cur1 is
      4  select * from dba_data_files;
      5  begin
      6     null;
      7  end;
      8  /警告: 创建的过程带有编译错误。SQL>
    SQL>
    SQL> create or replace procedure sp_DoHouseKeeping
      2  as
      3  cursor cur1 is
      4  select * from emp;
      5  begin
      6     null;
      7  end;
      8  /过程已创建。可能是权限上的bug,虽然有DBA的角色,也能查dba_data_files的表,但就是编译过不去,你用sys去建试试。
      

  11.   

    ... 可能是我这个SQL语句在ORACLE里面执行存在权限问题导致的,单纯语法角度看应该是OK的。
    多谢楼上几位。
      

  12.   

    create or replace procedure sp_DoHouseKeeping
    as
    strSQL    varchar2(2048);
    cursor mycursor is
    select
        'alter database datafile '''||a.file_name||''' resize '
        ||round(a.filesize - (a.filesize - c.hwmsize-100) *0.8)||'M' runstatement
        from
        (
            select file_id,file_name,round(bytes/1024/1024) filesize from dba_data_files
        ) a,
        (
            select file_id,round(max(block_id)*8/1024) HWMsize from dba_extents
            group by file_id
        ) c
        where a.file_id = c.file_id
              and a.filesize - c.hwmsize > 100;
    begin
    open mycursor;
    fetch mycursor into strSQL;
    loop
    exit when mycursor%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(strSQL);
    execute immediate strSQL;
    commit;
    fetch mycursor into strSQL;
    end loop;
    close mycursor;
    null;
    end;
    /改好了,用了sys用户,改写了下循环,就好用了。