只是理论问题:
嵌套表由于删除而变得稀疏,这可以通过在first
之间的next
到last
之间的索引序列中创建漏洞来证明。
但是,如果删除last
索引,则集合边界与修剪last
索引完全相同(或者就像集合从未扩展到该索引一样)。
有没有办法区分这种差异?
declare
type ct is table of varchar2(200);
a ct := ct('x','y','z');
b ct := ct('x','y','z');
begin
a.delete(3);
b.trim();
-- first=1, last=2, count=2 here for both a and b
a(3) := 'l'; -- legal since delete keeps room for 3rd element extended
--b(3) := 'l'; -- illegal since trim is inversion of extend
end;
换句话说,如果Alice删除并修剪Bob,我可以告诉谁创建了哪个集合(除了尝试在索引last+1
插入并捕获潜在的ORA-06533 Subscript beyond count
错误)?谢谢!
答案 0 :(得分:1)
这里的区别在于delete
后嵌套表变为稀疏但在trim
之后它仍然是密集。 PL / SQL没有提供(简单)工具来检查嵌套表是稀疏还是密集的 - 如果他正在使用稀疏或密集的嵌套表,那么程序员有责任一直知道。
在a.delete(3)
或b.trim
之后的特定示例中,PL / SQL为您提供了无法以编程方式检查a(3) := 'x'
或b(3) := 'x'
是否有效的工具。除非,正如您所指出的那样,尝试并捕获潜在的异常。通常,您必须跟踪嵌套的表大小。
我的经验法则是,始终保持其嵌套表密集,并使用关联数组进行稀疏集合。如果只需要嵌套表元素的子集,则为子集创建一个新的密集嵌套表。
示例强>
declare
type str_list_t is table of varchar2(1);
a str_list_t := str_list_t('a', 'b', 'c'); -- dense
b str_list_t := str_list_t('a', 'b', 'c'); -- dense
procedure d(p_strs in str_list_t) is
s varchar2(32767);
begin
s := '(count ' || p_strs.count || ')';
s := s || '(first ' || p_strs.first || ')';
s := s || '(last ' || p_strs.last || ')';
s := s || '(';
for i in p_strs.first .. p_strs.last
loop
s := s || '(' || i || ' ' || p_strs(i) || ')';
end loop;
s := s || ')';
dbms_output.put_line(s);
end;
begin
a.delete(3); d(a); -- collection becomes sparse
b.trim; d(b); -- remains dense
-- exists won't help you as a(3) doesn't exists and exists returns false
if a.exists(3) then a(3) := 'C'; end if;
if b.exists(3) then b(3) := 'C'; end if;
d(a);
d(b);
a(3) := 'D'; d(a); -- ok
b(3) := 'D'; d(b); -- ORA-06533: Subscript beyond count
end;
/
<强>结果
(count 2)(first 1)(last 2)((1 a)(2 b))
(count 2)(first 1)(last 2)((1 a)(2 b))
(count 2)(first 1)(last 2)((1 a)(2 b))
(count 2)(first 1)(last 2)((1 a)(2 b))
(count 3)(first 1)(last 3)((1 a)(2 b)(3 D))
declare
*
ERROR at line 1:
ORA-06533: Subscript beyond count
ORA-06512: at line 35