2016-09-15 59 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'不適用於嵌套表格,它可能會返回內部容量)。 –

相關問題