PLS-00382: 填充关联数组时表达式的类型错误 table

PLS-00382: expression is of wrong type in populating an associative array table

我的数据库中有 table 这种结构

现在我想要它里面的所有值都在一个关联数组中,该数组由 job_id%type 索引,它是一个 varchar2,所以我在创建一个程序来测试它之前先创建了这个匿名块,然后我想用结果填充我的关联数组:

DECLARE
    TYPE jobs_tab_type IS TABLE OF jobs%rowtype INDEX BY jobs.job_id%type;
    jobstab jobs_tab_type;
BEGIN

    FOR rec IN (SELECT * FROM jobs)
    LOOP
        jobstab(rec.job_id) := rec.job_id;
    END LOOP;
END;

我确定这是错误的方法,因为我遇到了这个错误:PLS-00382: expression is of wrong type,但同时我不知道不知道是否有任何正确的方法可以做到这一点。我看过文档,但所有示例都是使用用户定义的字符串来保存 job_id,但问题是我需要索引 job_id 而不是用户定义的字符串。在 PL/SQL 中有什么方法可以解决这个问题吗?

你的关联数组的值是整条记录。因此,只需从您的这行代码中删除 .job_id

jobstab(rec.job_id) := rec.job_id;

换句话说,该行应该是

jobstab(rec.job_id) := rec;

参考this db<>fiddle

不需要 INDEX BY jobs.job_id%type 的索引。它使您的代码更加复杂。 INDEX BY 确定集合的 index - 即用于指示集合中位置的字符。 不需要 成为您从中获取 %rowtype 的 table 中的一列。 如果您想根据有意义的字符串引用集合,通常会使用 INDEX BY VARCHAR2,例如 capitals('United States') = 'Washingston'

现在,关于你的问题。这是原问题的答案:


create table jobs
(job_id VARCHAR2(10)
,job_title VARCHAR2(30)
,min_salary NUMBER
,max_salary NUMBER
);

INSERT INTO jobs (job_id, job_title, min_salary, max_salary) VALUES ('a','CLERK',100,500);
INSERT INTO jobs (job_id, job_title, min_salary, max_salary) VALUES ('b','PRESIDENT',1000,5000);
INSERT INTO jobs (job_id, job_title, min_salary, max_salary) VALUES ('c','SALESMAN',500,800);

DECLARE
    TYPE jobs_tab_type IS TABLE OF jobs%rowtype INDEX BY jobs.job_id%type;
    jobstab jobs_tab_type;
    l_idx VARCHAR2(100);  
BEGIN

    FOR rec IN (SELECT * FROM jobs)
    LOOP
        jobstab(rec.job_id) := rec;
    END LOOP;
    
    l_idx := jobstab.FIRST;     
    WHILE (l_idx IS NOT NULL) LOOP
      dbms_output.put_line(l_idx ||': '||jobstab(l_idx).job_title);
      l_idx := jobstab.NEXT(l_idx);
    END LOOP;
END;
/

a: CLERK
b: PRESIDENT
c: SALESMAN

请注意,在这个块中,循环遍历元素有点乏味,因为索引不是整数。现在让我们看一下相同的功能,但使用 INDEX BY BINARY_INTEGER:

DECLARE
    TYPE jobs_tab_type IS TABLE OF jobs%rowtype INDEX BY BINARY_INTEGER;
    jobstab jobs_tab_type;
    l_idx NUMBER := 1;
BEGIN

-- example 1: using a cursor for loop

--    FOR rec IN (SELECT * FROM jobs)
--    LOOP
--        jobstab(l_idx) := rec;
--        l_idx := l_idx + 1;
--    END LOOP;
    
-- example 2: using bulk collect
    SELECT * BULK COLLECT INTO jobstab FROM jobs;
    
    FOR r IN 1 .. jobstab.COUNT LOOP
       dbms_output.put_line(r ||': '||jobstab(r).job_title);
    END LOOP;
END;
/


1: CLERK
2: PRESIDENT
3: SALESMAN

由于数字索引,循环遍历集合的值更简单,而且它也可以使用 BULK COLLECT 语句隐式分配。