Oracle ORA-00911:使用execute immediate的字符无效

Oracle ORA-00911:使用execute immediate的字符无效,oracle,Oracle,下面是我用来动态创建partTiton的代码。我面临错误无效字符错误。在执行消息输出时,我没有遇到任何错误。请帮我解决这个问题 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

下面是我用来动态创建partTiton的代码。我面临错误无效字符错误。在执行消息输出时,我没有遇到任何错误。请帮我解决这个问题

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;

分号是语句分隔符;这是一个无效字符。您只能使用
executeimmediate
执行单个语句,不能构建一系列SQL语句并一次性执行它们。因此,您需要删除分号并将
executeimmediate
移动到循环中,删除语句的串联,并从每个语句中删除最后的分号:

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
参数。抓住别人通常是个坏主意。顺便说一句,
返回后的代码将永远不会被调用。但这有点离题了…

您可以只使用范围分区吗?然后将自动为您创建分区。hi Davek,同时创建表时间本身,并添加一个月的分区。以后我们需要添加一整年的分区的时候需要一个一个的添加。为了避免这种情况,我选择了这种方式。你能在这方面帮助我吗你的
dbms\u输出的输出是什么?