Sat*_*hat 13 oracle plsql associative-array oracle11g
我有一个由表列的行类型创建的关联数组.
举个例子,它就是这样的(表名不同,但结构是一样的):
这是表的DDL
CREATE TABLE employees
(
id NUMBER,
name VARCHAR2(240),
salary NUMBER
);
Run Code Online (Sandbox Code Playgroud)
这是我的程序正在做的事情:
DECLARE
TYPE table_of_emp
IS TABLE OF employees%ROWTYPE INDEX BY BINARY_INTEGER;
emp TABLE_OF_EMP;
BEGIN
IF emp IS NULL THEN
dbms_output.Put_line('Null associative array');
ELSE
dbms_output.Put_line('Not null');
END IF;
END;
Run Code Online (Sandbox Code Playgroud)
我认为这应该导致打印"Null associative array".但是,if条件失败并且执行跳转到else部分.
现在,如果我放入一个for循环来打印集合值
DECLARE
TYPE table_of_emp
IS TABLE OF employees%ROWTYPE INDEX BY BINARY_INTEGER;
emp TABLE_OF_EMP;
BEGIN
IF emp IS NULL THEN
dbms_output.Put_line('Null associative array');
ELSE
dbms_output.Put_line('Not null');
FOR i IN emp.first..emp.last LOOP
dbms_output.Put_line('Emp name: '
|| Emp(i).name);
END LOOP;
END IF;
END;
Run Code Online (Sandbox Code Playgroud)
然后程序单元引发异常,引用for循环线
ORA-06502:PL/SQL:数值或值错误
我认为是因为null关联数组.是否由于null关联数组而引发错误?
那么为什么第一次检查失败呢?我究竟做错了什么?
数据库服务器是Oracle 11g EE(版本11.2.0.3.0 64位)
Sha*_*nce 13
我认为这应该导致打印"Null associative array".这种假设对于关联数组是错误的.它们在声明时存在,但是是空的.对于其他类型的PL/SQL集合,这是正确的:
在初始化之前,嵌套表或varray在原子上为null; 集合本身是null,而不是它的元素.要初始化嵌套表或varray,请使用构造函数,这是一个与集合类型同名的系统定义函数.此函数根据传递给它的元素构造集合.
您必须为每个varray和嵌套表变量显式调用构造函数.关联数组是第三种集合,不使用构造函数.只要允许函数调用,就允许构造函数调用.初始化和引用集合
相比:
SQL> declare
2 type varchar2_100_aa is table of varchar2(100) index by binary_integer;
3 test varchar2_100_aa;
4 begin
5 test(1) := 'Hello';
6 dbms_output.put_line(test(1));
7 end;
8 /
Hello
PL/SQL procedure successfully completed.
SQL> declare
2 type varchar2_100_va is varray(100) of varchar2(100);
3 test varchar2_100_va;
4 begin
5 test(1) := 'Hello';
6 dbms_output.put_line(test(1));
7 end;
8 /
declare
*
ERROR at line 1:
ORA-06531: Reference to uninitialized collection
ORA-06512: at line 5
Run Code Online (Sandbox Code Playgroud)
变量数组正确完成:
SQL> declare
2 type varchar2_100_va is varray(10) of varchar2(100);
3 test varchar2_100_va;
4 begin
5 test := varchar2_100_va(); -- not needed on associative array
6 test.extend; -- not needed on associative array
7 test(1) := 'Hello';
8 dbms_output.put_line(test(1));
9 end;
10 /
Hello
PL/SQL procedure successfully completed.
Run Code Online (Sandbox Code Playgroud)
因为关联数组是空的first并且last为null,这就是您的第二个示例导致的结果ORA-06502: PL/SQL: Numeric or value error:
SQL> declare
2 type varchar2_100_aa is table of varchar2(100) index by binary_integer;
3 test varchar2_100_aa;
4 begin
5 dbms_output.put_line(test.count);
6 dbms_output.put_line(coalesce(to_char(test.first), 'NULL'));
7 dbms_output.put_line(coalesce(to_char(test.last), 'NULL'));
8 test(1) := 'Hello';
9 dbms_output.new_line;
10 dbms_output.put_line(test.count);
11 dbms_output.put_line(coalesce(to_char(test.first), 'NULL'));
12 dbms_output.put_line(coalesce(to_char(test.last), 'NULL'));
13 end;
14 /
0
NULL
NULL
1
1
1
PL/SQL procedure successfully completed.
Run Code Online (Sandbox Code Playgroud)
编辑还要注意关联数组可以是稀疏的.在循环之间的数字first,并last会引发异常的任何集合,是稀疏.而是使用first和next喜欢这样:( Last并prev循环另一个方向.)
SQL> declare
2 type varchar2_100_aa is table of varchar2(100) index by binary_integer;
3 test varchar2_100_aa;
4 i binary_integer;
5 begin
6 test(1) := 'Hello';
7 test(100) := 'Good bye';
8 dbms_output.put_line(test.count);
9 dbms_output.put_line(coalesce(to_char(test.first), 'NULL'));
10 dbms_output.put_line(coalesce(to_char(test.last), 'NULL'));
11 dbms_output.new_line;
12 --
13 i := test.first;
14 while (i is not null) loop
15 dbms_output.put_line(to_char(i, '999') || ' - ' || test(i));
16 i := test.next(i);
17 end loop;
18 end;
19 /
2
1
100
1 - Hello
100 - Good bye
PL/SQL procedure successfully completed.
Run Code Online (Sandbox Code Playgroud)
我不打算回答为什么第一次检查失败.我从来没有想过做这样的事情,我很惊讶它没有引起错误.
正如您所指出的那样,您在循环中获得异常的原因是索引emp.first不存在.
您应该检查是否存在此索引,而不是检查空值.您可以使用以下.exists(i)语法:
if not emp.exists(emp.first) then
dbms_output.put_line('Nothing in here.');
end if;
Run Code Online (Sandbox Code Playgroud)