Stored procedures pl/sql中过程执行的循环结果

Stored procedures pl/sql中过程执行的循环结果,stored-procedures,plsql,Stored Procedures,Plsql,我想制作一个存储过程来检查ORACLEDB表并为它们收集统计数据。 到目前为止,我已经做到了这一点,现在我想知道如何在同一个循环中捕获每一行的执行结果 declare comm varchar2(200); cursor c1 is select owner, table_name, num_rows, last_analyzed from dba_tables where num_rows>=500000 and owner not in

我想制作一个存储过程来检查ORACLEDB表并为它们收集统计数据。 到目前为止,我已经做到了这一点,现在我想知道如何在同一个循环中捕获每一行的执行结果

declare

    comm varchar2(200);

    cursor c1 is 
    select owner, table_name, num_rows, last_analyzed  from dba_tables
    where num_rows>=500000
    and owner not in ('SYS','SYSTEM')
    and last_analyzed <= sysdate -7
    order by 3 desc;


begin
    FOR V1 IN C1 LOOP

    comm:= 'EXEC DBMS_STATS.gather_table_stats( '''||V1.OWNER||''','''||V1.TABLE_NAME||''' , estimate_percent => DBMS_STATS.auto_sample_size);';

    EXECUTE IMMEDIATE comm;
    end loop;
end;

我试过了,现在就可以了。。。。谢谢你的回复

declare

    comm varchar2(200);


    cursor c1 is 
select owner, table_name, num_rows, last_analyzed  from dba_tables
where num_rows>=500000
and owner not in ('SYS','SYSTEM')
and last_analyzed <= sysdate -7
order by 3 desc;


begin
    FOR V1 IN C1 LOOP
    begin
      comm := 'begin DBMS_STATS.gather_table_stats( '''||V1.OWNER||''','''||V1.TABLE_NAME||''' , estimate_percent => DBMS_STATS.auto_sample_size); end;';
      --dbms_output.put_line('begin DBMS_STATS.gather_table_stats( '''||V1.OWNER||''' , '''||V1.TABLE_NAME||''' , estimate_percent => DBMS_STATS.auto_sample_size); end;') ;

    EXECUTE IMMEDIATE comm ;
    dbms_output.put_line( V1.TABLE_NAME || '------Ok------') ;
    exception 
    when others then 
    dbms_output.put_line(V1.TABLE_NAME || '------Not ok------' || 'SQLERRM: '|| SQLERRM || ' Format error stack : '||dbms_utility.format_error_stack) ;
    end;
    end loop;
end;

从纯粹的语法角度来看,您的代码可以是这样的:

begin
    for r in (
        select t.owner, t.table_name, t.num_rows
        from   dba_tables t
               left join dba_external_tables x
                    on  x.owner = t.owner and x.table_name = t.table_name
        where  t.owner not in ('SYS','SYSTEM')
        and    t.temporary = 'N'
        and    x.table_name is null
        and    t.num_rows >= 500000
        and    t.last_analyzed <= sysdate -7
    )
    loop
        begin
            dbms_stats.gather_table_stats(r.owner, r.table_name);
        exception
            when others then
                dbms_output.put_line('Error gathering stats on table '|| r.owner||'.'||r.table_name||': '|| sqlerrm);
        end;
    end loop;
end;
我排除了外部表和临时表,并跳过了失败

然而,我不确定这是一个好方法

是否确实要为每个其他架构中的每个表收集统计信息

对于没有任何统计信息的表,会发生什么情况

是否确实要对每个表使用默认方法选项设置?有些表可能有精心编制的直方图和扩展的统计列组,或者它们可能故意完全避免使用直方图


是否会有大量的表格需要花费数小时才能处理?如果是这样,您准备好让脚本运行几天了吗?

您可以尝试使用EXECUTE IMMEDIATE comm RETURNING field1进入v_field1。;您希望该语句返回什么值?另外,EXEC是一个SQL*Plus调用:executeimmediate不喜欢它。您需要将调用框架化为一个匿名PL/SQL块:begindbms_stats.gather_table_stats。。。;终止我希望为每个执行立即行输出成功完成,比如:PL/SQL过程。安装soapbox!只是好奇,为什么要整理桌子呢。强迫一张表上的统计数据在3周内未分析,而强迫一张表上的统计数据在2周内未分析,这真的有什么区别吗。它们都将在相同的脚本运行中完成。如果没有任何区别,我的一个癖好就不合适了。哦,好吧,离开soapbox。对于没有stats num_行且上次分析的表为空的表呢?您真的需要临时表和外部表的统计信息吗?为什么要使用executeimmediate,而不是像通常那样调用dbms_stats,即调用dbms_输出的方式?