ORA-06533: PL/SQL 中的下标超出计数 ORA-06512

ORA-06533: Subscript beyond count ORA-06512 in PL/SQL

我想要一个 10 x 10 的网格,数字从 1 到 100 它给了我这个错误 ORA-06533: 下标超出计数 ORA-06512: 在第 25 行

ORA-06512:在“SYS.DBMS_SQL”,第 1721 行

我不明白这个错误,我无法解决 有人可以帮我吗

DECLARE
    -- PL SQL code to create and fill a two-dimensional array
    -- create VARRAY type of 10 integers
    TYPE array_10_int  IS VARRAY(10) of PLS_INTEGER;

    -- create VARRAY type of array_10_int 
    TYPE grid_100_int IS VARRAY(10) of array_10_int;
    
    -- declare a variable of the grid_100_int type
    grid_var grid_100_int;
    
    -- declare counters 
    i PLS_INTEGER := 0;
    j PLS_INTEGER :=0;
    M PLS_INTEGER :=0;
    N PLS_INTEGER :=0;

BEGIN
    grid_var := grid_100_int();
    -- TO DO : use nested loop to fill grid_var with numbers 1- 100
    /** YOUR CODE HERE **/
    M:=0;
    Loop
        M:=M+1;
        N:=0;
        LOOP
           J:=j+1;
            If grid_var(M)(N)<100 THEN
               DBMS_OUTPUT.PUT(' ' || grid_var(M)(N) || ' ');
            ELSE
               DBMS_OUTPUT.PUT( grid_var(M)(N) || ' ');
            END IF;
            
            EXIT WHEN (N =100);
        END LOOP;
        dbms_output.put_line(' ');
        EXIT WHEN (M=10);
    END LOOP;
    

-- Print the grid with nested loop
    i:=0;
    LOOP --outer loop
        i := i+1;
        j := 0;
        LOOP    -- inner loop
            j:= j+1;
            IF grid_var(i)(j) < 10 THEN
                DBMS_OUTPUT.PUT(' ' || grid_var(i)(j) || ' ');
            ELSE
                DBMS_OUTPUT.PUT( grid_var(i)(j) || ' ');
            END IF;
           
            EXIT WHEN (j =10);
        END LOOP;
        dbms_output.put_line(' ');
        EXIT WHEN (i =10);
    END LOOP;    
    
    
END;

再看一眼
创建多维数组 (10 x 10) 是一件棘手的事情。它们实际上是一个集合的集合。此外,每个都有相同的定义和存在要求:元素必须在被引用之前存在,或者被 extendarray initialization 引用。以下代码在引用每个数组之前对其进行初始化。它还使用 FOR loop letting Postgres handle the setting, incrementing subscripts and loop exiting, rather than manually. See demo.

declare
    -- PL SQL code to create and fill a two-dimensional array
    -- create VARRAY type of 10 integers
    type array_10_int  is varray(10) of pls_integer;  

    -- create VARRAY type of array_10_int 
    type grid_100_int is varray(10) of array_10_int ;  
    
    -- declare a variable of the grid_100_int type
    grid_var grid_100_int;
begin

    grid_var := grid_100_int(null,null,null,null,null,null,null,null,null,null);  -- initialize outer array 
    -- TO DO : use nested loop to fill grid_var with numbers 1- 100
    /* YOUR CODE HERE */
    
    for m in 1 .. 10 
    loop 
        grid_var(m) := array_10_int(null,null,null,null,null,null,null,null,null,null); -- initialize the inner array   
        for n in 1 .. 10 
        loop                                  
            grid_var(m)(n) := 10*(m-1)+ n;   
        end loop ; 
    end loop; 
 
-- Print the grid with nested loop
      for m in 1 .. 10 
      loop
         for n in 1 .. 10 
         loop 
            dbms_output.put_line ('grid_var(' || to_char(m) 
                                 || ')(' || to_char(n) 
                                 || ') = ' || to_char(grid_var(m)(n))
                                 );    
        end loop ;   
    end loop; 
    
end;

要点: 在 Oracle 中创建和使用多维数组是可行的。 But use them only when there is no other option. 它们增加了相当大的复杂性,通常是不必要的,而且人们很难理解。 (上面的很简单。)
带走 2 让 Postgres 控制你的循环。不易出错,代码更少,更易于阅读。


PL/SQL 数组索引以 1 开头。但是在下面的代码中,局部变量 n 首次用作索引时为 0。

 Loop
        M:=M+1;
        N:=0;
        LOOP
           J:=j+1;
            If grid_var(M)(N)<100 THEN    --<<< n is 0 which throws your  exception.
                ... 
               EXIT WHEN (N =100);   --<<< NEVER occurs, N is not  

不幸的是,这不是您唯一的问题(按此逻辑)。您的退出语句是条件 EXIT WHEN (N =100); 永远不会满足。在进入循环之前初始化变量 n,但从不在循环中递增它。
将以上调整为:

    Loop
                M:=M+1;
                N:=1;          -- <<< change here 
                LOOP
                   J:=j+1;
                    If grid_var(M)(N)<=100 THEN 
                    ... 
                   EXIT WHEN (N >100);   --<<< NEVER occurs, N is not incremented in the loop;
                END LOOP;  

你的另一个循环似乎没有同样的问题,但你应该检查一下。