2016-09-15 58 views
2

只是理论上的问题:我可以告诉PLSQL集合中删除了来自修剪的PLSQL集合的最后一个元素吗?

嵌套表可以变得稀疏由于缺失,可以通过从first跨越next S IN索引序列创始孔直到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删除和鲍勃修整,我可以告诉谁做哪个集合(除了使企图指数last+1插入和捕捉到潜在的ORA-06533错误Subscript beyond count)?谢谢!

回答

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 
+0

感谢完整的答案。我有点期待它。遗憾的是,这样的信息并不容易获得(例如'limit'不适用于嵌套表格,它可能会返回内部容量)。 –

相关问题