oracle 06533. 00000 -“下标无法计数”

2lpgd968  于 2023-02-03  发布在  Oracle
关注(0)|答案(1)|浏览(115)

我有一个plsql块,它用另外两个表的信息填充一个表,我必须使用一个变量数组:

DECLARE nombre_grupo VARCHAR2(15);
    direccion_tipo direccion;
    persona_tipo persona;
    personas_array personas := personas();
    CURSOR departamento IS
    SELECT * FROM departamentos;
    CURSOR empleado IS
    SELECT * FROM empleados, departamentos
    WHERE empleados.dept_no = departamentos.dept_no;
    i INTEGER;
BEGIN
    FOR departamento IN (SELECT * FROM departamentos) LOOP
    nombre_grupo := departamento.dnombre;
    i := 1;
    personas_array := personas();
    FOR empleado IN (SELECT * FROM empleados WHERE dept_no = departamento.dept_no) LOOP
        direccion_tipo := DIRECCION(departamento.loc, 'NULL', empleado.dir);
        personas_array(i) := PERSONA(empleado.emp_no, empleado.apellido,
        direccion_tipo, empleado.fecha_alt);
        i := i + 1;
    END LOOP;
    INSERT INTO grupos VALUES (nombre_grupo, personas_array);
    END LOOP;
END;

下面是典型的人物角色:

CREATE OR REPLACE TYPE personas AS VARRAY(5) OF PERSONA

因此,当我执行该块时,它到达personas_array(i)位,无论i的值是什么,它都会以“下标超出计数”错误退出执行。
我已经删除并重新创建了类型角色,我还尝试在过程中创建类型,但是它不能插入到表中

enxuqcxy

enxuqcxy1#

SQL初学者的一些提示:
不要学习30年前的Oracle连接语法,使用现代的ANSI连接语法,即

SELECT * 
FROM empleados 
   JOIN departamentos ON empleados.dept_no = departamentos.dept_no;

游标是多余的。请使用

DECLARE 
    CURSOR cur_departamento IS
    SELECT * 
    FROM departamentos;   
BEGIN
    FOR departamento IN cur_departamento LOOP
       ...
    END LOOP;
END;

DECLARE 
BEGIN
    FOR departamento IN (SELECT * FROM departamentos) LOOP
       ...
    END LOOP;
END;

您还可以使用以下命令:

DECLARE 
    CURSOR cur_empleados(d IN EMPLEADOS.DEPT_NO%TYPE) IS
    SELECT * 
    FROM EMPLEADOS
    WHERE dept_no = d;

   /*
   -- Do not use this!
    CURSOR cur_empleados(dept_no IN EMPLEADOS.DEPT_NO%TYPE) IS
    SELECT * 
    FROM EMPLEADOS
    WHERE EMPLEADOS.dept_no = dept_no;  -> will return all rows
    */    

BEGIN
   FOR departamento IN (SELECT * FROM departamentos) LOOP
      FOR empleado  IN cur_empleados(departamento.dept_no) LOOP
         ...
      END LOOP;
   END LOOP;
END;

根据我的感觉,varray经常是学生材料的一部分,但在真实的生活中几乎没有使用。
使用字符串'NULL'很可能不是你想要的。使用文字NULL,即

DIRECCION(departamento.loc, NULL, empleado.dir)

类型VARRAY(5) OF PERSONA定义了一个可变数组,其最大大小为5个元素。当您使用personas_array := personas();初始化它时,实际大小为0。您需要扩展该可变数组。
您的代码可能如下所示:

DECLARE 

    nombre_grupo VARCHAR2(15); 
    direccion_tipo direccion;
    persona_tipo persona;
    personas_array personas;

    i INTEGER;
    
BEGIN
    FOR departamento IN (SELECT * FROM departamentos) LOOP
        nombre_grupo := departamento.dnombre;
        i := 1;
        personas_array := personas();
        FOR empleado IN (SELECT * FROM empleados WHERE dept_no = departamento.dept_no AND ROWNUM <= 5) LOOP
            direccion_tipo := DIRECCION(departamento.loc, NULL, empleado.dir);
            personas_array.extend();
            personas_array(i) := PERSONA(empleado.emp_no, empleado.apellido, direccion_tipo, empleado.fecha_alt);
            i := i + 1;
        END LOOP;
        INSERT INTO grupos VALUES (nombre_grupo, personas_array);
    END LOOP;
END;

需要注意的是,这样的过程性能会很低。专业的做法是创建嵌套表,然后用一个命令插入数据:

CREATE OR REPLACE TYPE personas_NT AS TABLE OF PERSONA;

INSERT INTO grupos VALUES (nombre_grupo, personas_array)
SELECT dnombre, 
    CAST(MULTISET(
        SELECT 
            emp_no, 
            apellido, 
            DIRECCION(dept.loc, NULL, dir), 
            fecha_alt
        FROM EMPLEADOS
        WHERE dept_no = dept.dept_no
    ) AS personas_NT) AS personas_array
FROM DEPARTAMENTOS dept;

但也许,那会是“高级”SQL课程中的一章。

相关问题