【问题标题】:Oracle creating a dynamic plsql commandOracle 创建动态 plsql 命令
【发布时间】:2022-01-25 18:48:43
【问题描述】:

我正在尝试组合一个过程,该过程计算表中每个 PARTITION 的行数,但出现语法错误:

错误:PROCEDURE COUNT_PARTITION 行/列:14/31 PLS-00103:在预期以下情况之一时遇到符号“(”:

我知道这不是最有效的方法,我可以使用 num_rows 列以及收集统计信息来获得相同的结果。

以下是我的测试用例。我知道问题出在“cmd”调用的构造上,但我似乎无法让它工作。任何帮助将不胜感激。


CREATE OR REPLACE PROCEDURE cmd(p_cmd varchar2) 
 authid current_user
is
BEGIN 

dbms_output.put_line(p_cmd);

 execute immediate p_cmd;

END;
/


CREATE  OR REPLACE PROCEDURE
count_partition(
  p_tab varchar2
) authid current_user
is
  v_cnt integer;
BEGIN

   for cur_rec in (select table_name, partition_name,
partition_position
 FROM user_tab_partitions where table_name = p_tab order by partition_position) loop
      
   cmd ('select count(*) /*+ parallel(a,8) */
from ' ||p_tab|| 'PARTITION ' ('||cur_rec.partition_name||')' INTO v_cnt);
    DBMS_OUTPUT.PUT_LINE(cur_rec.table_name || ' ' || cur_rec.partition_name || ' ' || v_cnt || ' rows');
   end loop;
END;

【问题讨论】:

  • 问题不在于 cmd,您的程序有语法错误。见db<>fiddle。甚至 SQL 代码的本地语法突出显示也表明引号放错了位置。您需要更正串联
  • 我知道错误在哪里。我的意思是说创建命令。为糟糕的语法道歉
  • cmd() 是否总是进行计数?您不能动态传递 into 子句。它可以传回值或报告计数本身。
  • 威廉·罗伯逊感谢您的回复。我使用 cmd 函数来执行诸如 ALTER table drop PARTITION 之类的操作……这是我第一次尝试使用它来返回计数。我不确定这是否是我收到语法错误的原因。您能否建议一个代码片段解决方法,即使这意味着不使用 cmd 函数
  • 要接收来自execute immediate 的内容,您需要使用[bulk collect] into some_var。您不能将 into 放在普通 SQL 中,因为它没有任何外部变量。但是对于这个特定的任务,您可以在dbms_xmlgen.getxml 的帮助下执行动态 SQL 语句并接收纯 SQL 的结果。见db<>fiddle

标签: oracle plsql procedure


【解决方案1】:

创建了一个过程和包装器


CREATE  OR REPLACE PROCEDURE
count_partition(
  p_tab varchar2
) authid current_user
is
  sql_stmt varchar2(1024);
row_count number;

cursor get_tab is
select table_name,
         partition_name
from user_tab_partitions
where table_name=p_tab;

BEGIN 
    for get_tab_rec in   get_tab loop
    BEGIN
    sql_stmt := 'select count(*) /*+ parallel(a,4) */ from ' ||get_tab_rec.table_name||' partition ( '||get_tab_rec.partition_name||' )';

--dbms_output.put_line(sql_stmt);

    EXECUTE IMMEDIATE sql_stmt INTO row_count;

dbms_output.put_line('Table '||rpad(get_tab_rec.table_name
||'('||get_tab_rec.partition_name||')',50)
||' '||TO_CHAR(row_count)||' rows.');
exception when others then
dbms_output.put_line
('Error counting rows for table '||get_tab_rec.table_name);
    END;
  END LOOP;
END;
/

BEGIN 
    FOR cur_r IN(
      SELECT TABLE_NAME FROM USER_PART_TABLES 
)
   LOOP
  --DBMS_OUTPUT.put_line('Table '|| cur_r.table_name);

  count_partition (cur_r.table_name);
  
  END LOOP;
END;

~~

【讨论】:

    猜你喜欢
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    相关资源
    最近更新 更多