下面的代码用于动态创建partititon。我面临错误无效的chararcter错误。在执行消息输出时,我没有遇到任何错误。请帮我解决这个问题。
create or replace package shs_pk_dyn_par is
procedure dynamic_proc ( p_table_name in varchar2,p_month_from in number,p_month_to in number,p_status out varchar2 , p_messgae out varchar2 );
end;
create or replace package body shs_pk_dyn_par is
procedure dynamic_proc ( p_table_name in varchar2,p_month_from in number,p_month_to in number,p_status out varchar2 , p_messgae out varchar2 ) is
v_sql varchar2(4000);
v_month_from number;
v_month_to number;
v_append number;
v_year number;
v_p_year number;
v_p_check number;
begin
p_status := 'S';
p_messgae := 'Success';
v_month_from := 0; v_month_to := 0;v_sql :=null;v_append:=null;v_year:=null;v_p_year:=null;
v_p_check := null;
v_month_from := substr(p_month_from,5,6 );
v_month_to := substr(p_month_to,5,6 );
v_year := substr(p_month_to,1,4 );
---v_sql := ' ALTER TABLE '||p_table_name||' ADD';
for i in v_month_from..v_month_to
loop
if length(i) = 1
then
v_append := 0;
else
v_append := null;
end if;
v_p_year :=null;
v_p_year := i+1;
if length(v_p_year) = 1
then
v_p_check := v_year||trim(v_append)||v_p_year;
else
v_p_check := v_year||v_p_year;
end if;
dbms_output.put_line('v_p_check'||'='||v_p_check);
if i=1
then
v_sql := ' ALTER TABLE '||p_table_name||' ADD PARTITION P_'||v_year||trim(v_append)||i||' VALUES LESS THAN ('||v_p_check||')'||';';
else
v_sql := v_sql||chr(10)||' ALTER TABLE '||p_table_name||' ADD PARTITION P_'||v_year||trim(v_append)||i||' VALUES LESS THAN ('||v_p_check||')'||';';
end if;
end loop;
dbms_output.put_line(v_sql);
begin
execute immediate ( v_sql );
exception when others
then
p_status := 'F';
p_messgae := 'Failure'||sqlerrm||dbms_utility.format_error_backtrace;
return;
dbms_output.put_line('exec'||sqlerrm||dbms_utility.format_error_backtrace);
end;
exception when others
then
p_status := 'F';
p_messgae := 'Failure'||sqlerrm||dbms_utility.format_error_backtrace;
return;
dbms_output.put_line('dynamic_proc'||sqlerrm||dbms_utility.format_error_backtrace);
end;
end;
For Execution
-----------------------------------------
declare
p_status varchar2(1);
p_message varchar2(4000);
begin
shs_pk_dyn_par.dynamic_proc('EMPLOYEES_PAR',201302,201311,p_status,p_message);
dbms_output.put_line('p_status'||'='||p_status||'='||'p_messgae'||'='||p_message);
end;
答案 0 :(得分:1)
分号是一个语句分隔符;这是无效的角色。您只能使用execute immediate
执行单个语句,不能一次性构建一系列SQL语句并执行它们。因此,您需要删除分号并将execute immediate
移动到循环中,删除语句的串联,并从每个单独的语句中删除最后一个分号:
begin
...
loop
...
dbms_output.put_line('v_p_check'||'='||v_p_check);
v_sql := ' ALTER TABLE '||p_table_name
||' ADD PARTITION P_'||v_year||trim(v_append)||i
||' VALUES LESS THAN ('||v_p_check||')';
dbms_output.put_line(v_sql);
execute immediate ( v_sql );
end loop;
exception when others
then
p_status := 'F';
p_messgae := 'Failure'||sqlerrm||dbms_utility.format_error_backtrace;
return;
end;
(添加换行符只是为了停止代码滚动)
你也需要查看你的异常处理程序;我可能只是删除了附加到该子块的版本,因为它似乎有点无意义,但如果你真的想要,你仍然可以将每个调用包装在它自己的块中。
我认为你根本不需要任何异常处理程序 - 不确定为什么你不会让调用者自己处理异常而不是必须设置out
参数。捕获others
通常是一个坏主意。偶然地,return
之后的代码永远不会被调用。但这有点偏离主题......