【问题标题】:PL-SQL: returning error - inserting elements into (user input) index with shifting all the elements to element[i+1]PL-SQL:返回错误 - 将元素插入(用户输入)索引并将所有元素移动到元素 [i+1]
【发布时间】:2021-12-04 08:33:23
【问题描述】:
TYPE arr is VARRAY(10) of VARCHAR(32);
ar arr := arr('1', '1', '1');
idx INTEGER(100);
tmp INTEGER(100);
val VARCHAR(32);

PROCEDURE APPENDARR (arr IN OUT arr, idx IN, val IN) IS

BEGIN
    if(idx > arr.LIMIT) then
    tmp := (idx - arr.LIMIT);
    arr.extend(tmp);

    FOR i in REVERSE idx..arr.LAST LOOP
    arr(i) := arr(i - 1);
    if(arr(i) = arr(idx)) THEN
    arr(i) := val;
    END IF;
    END LOOP;
    ELSE
    arr.extend();
    arr(idx) := val;
    END IF;


END; 

错误代码: ORA-06550:第 10 行,第 48 列: PLS-00103:在预期以下情况之一时遇到符号“,”:

出来 long double ref char 时间 时间戳 间隔 日期 二进制 国字nchar

谁能帮我解决我的错误?抱歉英语不是我的母语,但我尽力了:)!

【问题讨论】:

    标签: sql oracle plsql


    【解决方案1】:

    我猜这是包的一部分,否则你需要create or replace 语法。出于演示目的,我把它放在一个匿名块中只是为了测试编译。

    两个问题:

    1. integer 不需要精确,它只是 integer
    2. idxval 参数缺少数据类型。

    以下编译(我没有检查它的作用或是否有更好的实现):

    declare
        type arr is varray(10) of varchar(32);
        ar  arr := arr('1', '1', '1');
        idx integer;
        tmp integer;
        val varchar(32);
    
        procedure appendarr
            ( arr in out arr
            , idx in integer
            , val in varchar2 )
        is
        begin
            if idx > arr.limit then
                tmp := idx - arr.limit;
                arr.extend(tmp);
            
                for i in reverse idx .. arr.last loop
                    arr(i) := arr(i - 1);
    
                    if arr(i) = arr(idx) then
                        arr(i) := val;
                    end if;
                end loop;
            else
                arr.extend();
                arr(idx) := val;
            end if;
        
        end;
    begin
        null;
    end;
    

    PL/SQL if 条件由 then 关键字终止,因此它们不像其他语言那样需要括号,所以我删除了它们。

    此外,您在顶部声明了变量idxtmpval,它们在任何地方都没有使用,并且它们也与过程中的局部变量具有相同的名称,这可能会造成混淆。如果没有更多您未展示的代码使用它们,也许您可​​以摆脱它们。

    编辑:根据要求,这是一个独立程序的样子:

    create or replace type arr as varray(10) of varchar(32)
    /
    
    create or replace procedure appendarr
        ( arr in out arr
        , idx in integer
        , val in varchar2 )
    as
        tmp integer;
    begin
        if idx > arr.limit then
            tmp := idx - arr.limit;
            arr.extend(tmp);
    
            for i in reverse idx .. arr.last loop
                arr(i) := arr(i - 1);
                if arr(i) = arr(idx) then
                    arr(i) := val;
                end if;
            end loop;
        else
            arr.extend();
            arr(idx) := val;
        end if;
        
    end appendarr;
    /
    

    (某些开发工具需要 / 字符来分隔块,但它不是 PL/SQL 语言本身的一部分。)

    似乎目标是将值val 插入到数组arr 的元素idx 中,将现有值上移一位。但是,它并不完全有效:

    declare
        ar  arr := arr('First', 'Second');
    begin
        appendarr
        ( arr => ar
        , idx => 2
        , val => 'New value' );
    
        for i in ar.first..ar.last loop
            dbms_output.put_line(i||' '||ar(i));
        end loop;
    end;
    
    1 First
    2 New value
    3 
    

    固定版本:

    create or replace type varchar2_tt as table of varchar2(50)
    /
    
    create or replace procedure varchar2_tt_append
        ( arr in out varchar2_tt
        , pos in pls_integer default null
        , val in varchar2 )
    as
        idx pls_integer := nvl(pos,arr.last +1);
    begin
        if idx > arr.last then
            arr.extend(idx - arr.last);
        else
            arr.extend();
    
            for i in reverse greatest(idx,2)..arr.last loop
                arr(i) := arr(i - 1);
            end loop;
        end if;
    
        arr(idx) := val;
        
    end varchar2_tt_append;
    /
    

    测试:

    declare
        ar  varchar2_tt := varchar2_tt('First', 'Second', 'Third', 'Fourth');
    begin
        varchar2_tt_append
        ( arr => ar
        , pos => 1
        , val => 'New value' );
    
        for i in ar.first..ar.last loop
            dbms_output.put_line(i||' '||ar(i));
        end loop;
    end;
    
    1 New value
    2 First
    3 Second
    4 Third
    5 Fourth
    

    【讨论】:

    • 感谢您的快速响应,并感谢您提供的提示和示例(/更正)语法。我有一个问题,为什么 PL-SQL 编译这个过程没有这个语法是个问题:“begin null; end;”
    • 因为它不是一个独立的过程 (create or replace procedure appendarr),而且它与type arr 一起似乎是一个更大块的一部分。因此我把它放在一个虚拟块的declare 部分,只是为了测试编译它。如果要调用它,请将null; 替换为对过程的调用。
    • 所以基本上一个过程不能在没有额外匿名块的情况下编译?谢谢,不知道!
    • 我不是这么说的。如果您的意图是创建一个可重用的独立过程,那么您需要使用 create or replace procedure appendarr,并决定如何声明类型 arr
    • 感谢您的快速响应,您能否举例说明一下声明类型 arr 的含义?
    猜你喜欢
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多