Oracleのコレクションについて

この記事にはかなり論文スタイルがあります。 より詳細な内容は、記事の最後にある添付のビデオに記載されており、Oracleコレクションに関する講義が収録されています。



コレクションは、ほとんどのプログラミング言語で何らかの形で存在し、どこでも使用の点で同様の本質を持っています。 つまり、同じタイプのオブジェクトのセットを保存し、セット全体に対してアクションを実行したり、サイクル内のセットのすべての要素に対して同じアクションを実行したりできます。



コレクションは、Oracleでも同じように使用されます。



記事の内容







pl / sqlのコレクションの概要






コレクションの種類


収集タイプ アイテム数 インデックスの種類 密または疎 初期化なし 発表場所 SQLでの使用
連想配列

(テーブルによるインデックス)
設定されていません ひも

Pls_integer
密で疎 空の PL / SQLブロック

パッケージ
いや
VARRAY

(可変サイズの配列)
によって設定 整数 高密度のみ ヌル PL / SQLブロック

パッケージ

スキーマレベル
スキーマ固有のみ
入れ子になったテーブル 設定されていません 整数 密に作成すると、まばらになることがあります ヌル PL / SQLブロック

パッケージ

スキーマレベル
スキーマ固有のみ


コレクションの密度とは、コレクションの要素間にギャップや空きスペースがないことを意味します。 表からわかるように、一部のコレクションはスパースである可能性があります。 要素間にギャップがある場合があります。 これは、たとえば、コレクション内にインデックス1と4の要素があり、インデックス2と3には要素がないことを意味します。 この場合、2番目と3番目の要素のメモリスロットは存在し、コレクション(ネストされたテーブルの場合)に属しますが、オブジェクトを含まず、これらの要素の内容を読み取ろうとするとno_data_foundエラーが発生します。

詳細は、記事の最後にあるビデオ講義に記載されています。



連想配列




テーブルまたはpl / sqlテーブルによるインデックスとも呼ばれます。

タイプは次のように説明されます(assoc_array_type_def):。







に使用:





制限:

連想配列を埋めた後、セッション中にNLS_SORTおよびNLS_COMPパラメーターを変更すると、最初、最後、次、前のメソッドの呼び出しから予期しない結果が得られる場合があります。 また、連想配列をパラメーターとして別のデータベースに渡す際に、異なるNLS_SORTおよびNLS_COMP設定を持つ問題がある場合があります。



VARRAY


これは、順次保存されるアイテムの配列です。





タイプは次のように記述されます(varay_type_def):









次の場合に使用:





制限:

最大サイズ-2,147,483,647アイテム



入れ子になったテーブル


タイプは次のように記述されます(nested_table_type_def):









ネストされたテーブルを使用したセット操作


操作は、 ネストた表コレクションでのみ可能です。 操作に参加する両方のコレクションは同じタイプである必要があります。

操作の結果は、 ネストした表のコレクションでもあります



運営 説明
マルチセットユニオン 2つのコレクションの和集合を返します
マルチセットユニオンの区別 重複のない2つのコレクションの和集合を返します(重複を削除します)
マルチセットの交差 2つのコレクションの共通部分を返します
マルチセット交差の区別 重複のない2つのコレクションの共通部分を返します(重複を削除します)
セット 異なるコレクション(テイクのないコレクション)を返します
マルチセットを除く 2つのコレクションの差を返します
DISTINCTを除くマルチセット 2つのコレクションの違いを個別に返します(重複を削除します)


小さな例
小さな例( MULTISET EXCEPT DISTINCT操作の結果に注意してください)

 DECLARE TYPE nested_typ IS TABLE OF NUMBER; nt1 nested_typ := nested_typ(1,2,3); nt2 nested_typ := nested_typ(3,2,1); nt3 nested_typ := nested_typ(2,3,1,3); nt4 nested_typ := nested_typ(1,2,4); answer nested_typ; BEGIN answer := nt1 MULTISET UNION nt4; answer := nt1 MULTISET UNION nt3; answer := nt1 MULTISET UNION DISTINCT nt3; answer := nt2 MULTISET INTERSECT nt3; answer := nt2 MULTISET INTERSECT DISTINCT nt3; answer := SET(nt3); answer := nt3 MULTISET EXCEPT nt2; answer := nt3 MULTISET EXCEPT DISTINCT nt2; END;
      
      







結果:

 nt1 MULTISET UNION nt4: 1 2 3 1 2 4 nt1 MULTISET UNION nt3: 1 2 3 2 3 1 3 nt1 MULTISET UNION DISTINCT nt3: 1 2 3 nt2 MULTISET INTERSECT nt3: 3 2 1 nt2 MULTISET INTERSECT DISTINCT nt3: 3 2 1 SET(nt3): 2 3 1 nt3 MULTISET EXCEPT nt2: 3 nt3 MULTISET EXCEPT DISTINCT nt2: empty set
      
      









コレクションを使用した論理演算


運営 説明
IS NULL(IS NOT NULL) コレクションをNULLと比較します
比較= 2つのネストされたテーブルコレクションは、それらが同じタイプで、タイプがrecordのレコードを含まない場合に比較できます。 同じ要素セットを持っている場合は同じです(コレクション内の要素の格納順序に関係なく)
コレクションを括弧内のコレクションと比較します
部分集合 コレクションが別のコレクションのサブセットであるかどうかを確認します。
のメンバー 特定のアイテム(オブジェクト)がコレクションの一部であるかどうかを確認します。
セットです コレクションに重複が含まれているかどうかを確認します
空です コレクションが空かどうかを確認します




論理的な収集操作を使用する小さな例
 DECLARE TYPE nested_typ IS TABLE OF NUMBER; nt1 nested_typ := nested_typ(1, 2, 3); nt2 nested_typ := nested_typ(3, 2, 1); nt3 nested_typ := nested_typ(2, 3, 1, 3); nt4 nested_typ := nested_typ(); BEGIN IF nt1 = nt2 THEN DBMS_OUTPUT.PUT_LINE('nt1 = nt2'); END IF; IF (nt1 IN (nt2, nt3, nt4)) THEN DBMS_OUTPUT.PUT_LINE('nt1 IN (nt2,nt3,nt4)'); END IF; IF (nt1 SUBMULTISET OF nt3) THEN DBMS_OUTPUT.PUT_LINE('nt1 SUBMULTISET OF nt3'); END IF; IF (3 MEMBER OF nt3) THEN DBMS_OUTPUT.PUT_LINE('3 MEMBER OF nt3'); END IF; IF (nt3 IS NOT A SET) THEN DBMS_OUTPUT.PUT_LINE('nt3 IS NOT A SET'); END IF; IF (nt4 IS EMPTY) THEN DBMS_OUTPUT.PUT_LINE('nt4 IS EMPTY'); END IF; END;
      
      







結果:

 nt1 = nt2 nt1 IN (nt2,nt3,nt4) nt1 SUBMULTISET OF nt3 3 MEMBER OF nt3 nt3 IS NOT A SET nt4 IS EMPTY
      
      









収集方法


メソッド呼び出しの構文:
 collection_name.method
      
      





方法 種類 説明 テーブルごとのインデックス VARRAY 入れ子になったテーブル
削除 手続き コレクションからアイテムを削除します。 はい パラメータなしのバージョンのみ はい
トリム 手続き コレクションの最後からアイテムを削除します(コレクションの内部サイズで動作します) いや はい はい
延長 手続き コレクションの最後にアイテムを追加します。 いや はい はい
存在する 機能 アイテムがコレクション内にある場合、TRUEを返します。 はい はい はい
最初 機能 コレクションの最初のインデックスを返します はい はい はい
最後 機能 最後のコレクションインデックスを返します はい はい はい
COUNT 機能 コレクション内のアイテムの数を返します。 はい はい はい
限界 機能 コレクションが保存できるアイテムの最大数を返します。 いや はい いや
事前 機能 コレクション内の前のアイテムのインデックスを返します。 はい はい はい
次へ 機能 コレクション内の次のアイテムのインデックスを返します はい はい はい




削除する
  • 削除すると、すべてのアイテムが削除されます。 これらのアイテムを保存するために割り当てられたメモリをすぐにクリアします。
  • 削除(n)は、インデックスnの要素を削除します。 メモリが解放されません。 要素を復元する(つまり、新しい要素を設定する)と、前の要素と同じメモリを占有します。
  • Delete(n、m)は、間隔n..mのインデックスを持つ要素を削除します
  • コレクションに削除するアイテムがない場合、何も実行されません。
  • VARRAY型のコレクションの場合、パラメータなしのメソッドのバージョンのみが使用可能です




使用例
 DECLARE TYPE nt_type IS TABLE OF NUMBER; nt nt_type := nt_type(11, 22, 33, 44, 55, 66); BEGIN nt.DELETE(2); --    nt(2) := 2222; --  2-  nt.DELETE(2, 4); --    2-  4- nt(3) := 3333; --  3-  nt.DELETE; --    END;
      
      





結果:

 beginning: 11 22 33 44 55 66 after delete(2): 11 33 44 55 66 after nt(2) := 2222: 11 2222 33 44 55 66 after delete(2, 4): 11 55 66 after nt(3) := 3333: 11 3333 55 66 after delete: empty set
      
      









トリム






使用例
 DECLARE TYPE nt_type IS TABLE OF NUMBER; nt nt_type := nt_type(11, 22, 33, 44, 55, 66); BEGIN nt.TRIM; -- Trim last element nt.DELETE(4); -- Delete fourth element nt.TRIM(2); -- Trim last two elements END;
      
      





結果:

 beginning: 11 22 33 44 55 66 after TRIM: 11 22 33 44 55 after DELETE(4): 11 22 33 55 after TRIM(2): 11 22 33
      
      









延長






使用例
 DECLARE TYPE nt_type IS TABLE OF NUMBER; nt nt_type := nt_type(11, 22, 33); BEGIN nt.EXTEND(2, 1); -- Append two copies of first element nt.DELETE(5); -- Delete fifth element nt.EXTEND; -- Append one null element END;
      
      





結果:

 beginning: 11 22 33 after EXTEND(2,1): 11 22 33 11 11 after DELETE(5): 11 22 33 11 after EXTEND: 11 22 33 11
      
      









存在する




使用例
 DECLARE TYPE NumList IS TABLE OF INTEGER; n NumList := NumList(1, 3, 5, 7); BEGIN n.DELETE(2); -- Delete second element FOR i IN 1 .. 6 LOOP IF n.EXISTS(i) THEN DBMS_OUTPUT.PUT_LINE('n('||i||') = ' || n(i)); ELSE DBMS_OUTPUT.PUT_LINE('n('||i||') does not exist'); END IF; END LOOP; END;
      
      









最初と最後




使用例
 DECLARE TYPE aa_type_str IS TABLE OF INTEGER INDEX BY VARCHAR2(10); aa_str aa_type_str; BEGIN aa_str('Z') := 26; aa_str('A') := 1; aa_str('K') := 11; aa_str('R') := 18; DBMS_OUTPUT.PUT_LINE('Before deletions:'); DBMS_OUTPUT.PUT_LINE('FIRST = ' || aa_str.FIRST); DBMS_OUTPUT.PUT_LINE('LAST = ' || aa_str.LAST); aa_str.DELETE('A'); aa_str.DELETE('Z'); DBMS_OUTPUT.PUT_LINE('After deletions:'); DBMS_OUTPUT.PUT_LINE('FIRST = ' || aa_str.FIRST); DBMS_OUTPUT.PUT_LINE('LAST = ' || aa_str.LAST); END;
      
      





結果:

 Before deletions: FIRST = A LAST = Z After deletions: FIRST = K LAST = R
      
      









カウント


使用例
 DECLARE TYPE NumList IS VARRAY(10) OF INTEGER; n NumList := NumList(1, 3, 5, 7); BEGIN DBMS_OUTPUT.PUT('n.COUNT = ' || n.COUNT || ', '); DBMS_OUTPUT.PUT_LINE('n.LAST = ' || n.LAST); n.EXTEND(3); DBMS_OUTPUT.PUT('n.COUNT = ' || n.COUNT || ', '); DBMS_OUTPUT.PUT_LINE('n.LAST = ' || n.LAST); n.TRIM(5); DBMS_OUTPUT.PUT('n.COUNT = ' || n.COUNT || ', '); DBMS_OUTPUT.PUT_LINE('n.LAST = ' || n.LAST); END;
      
      





結果

 n.COUNT = 4, n.LAST = 4 n.COUNT = 7, n.LAST = 7 n.COUNT = 2, n.LAST = 2
      
      









制限




使用例
 DECLARE TYPE aa_type IS TABLE OF INTEGER INDEX BY PLS_INTEGER; aa aa_type; -- associative array TYPE va_type IS VARRAY(4) OF INTEGER; va va_type := va_type(2, 4); -- varray TYPE nt_type IS TABLE OF INTEGER; nt nt_type := nt_type(1, 3, 5); -- nested table BEGIN aa(1) := 3; aa(2) := 6; aa(3) := 9; aa(4) := 12; DBMS_OUTPUT.PUT_LINE('aa.COUNT = ' || aa.count); DBMS_OUTPUT.PUT_LINE('aa.LIMIT = ' || aa.limit); DBMS_OUTPUT.PUT_LINE('va.COUNT = ' || va.count); DBMS_OUTPUT.PUT_LINE('va.LIMIT = ' || va.limit); DBMS_OUTPUT.PUT_LINE('nt.COUNT = ' || nt.count); DBMS_OUTPUT.PUT_LINE('nt.LIMIT = ' || nt.limit); END;
      
      





結果:

 aa.COUNT = 4 aa.LIMIT = va.COUNT = 2 va.LIMIT = 4 nt.COUNT = 3 nt.LIMIT =
      
      









前と次




使用例
 DECLARE TYPE nt_type IS TABLE OF NUMBER; nt nt_type := nt_type(18, NULL, 36, 45, 54, 63); BEGIN nt.DELETE(4); DBMS_OUTPUT.PUT_LINE('nt(4) was deleted.'); FOR i IN 1 .. 7 LOOP DBMS_OUTPUT.PUT('nt.PRIOR(' || i || ') = '); print(nt.PRIOR(i)); DBMS_OUTPUT.PUT('nt.NEXT(' || i || ') = '); print(nt.NEXT(i)); END LOOP; END;
      
      





結果:

 nt(4) was deleted. nt.PRIOR(1) = nt.NEXT(1) = 2 nt.PRIOR(2) = 1 nt.NEXT(2) = 3 nt.PRIOR(3) = 2 nt.NEXT(3) = 5 nt.PRIOR(4) = 3 nt.NEXT(4) = 5 nt.PRIOR(5) = 3 nt.NEXT(5) = 6 nt.PRIOR(6) = 5 nt.NEXT(6) = nt.PRIOR(7) = 6 nt.NEXT(7) =
      
      









一括収集






使用例
 DECLARE TYPE NumTab IS TABLE OF employees.employee_id%TYPE; TYPE NameTab IS TABLE OF employees.last_name%TYPE; CURSOR c1 IS SELECT employee_id,last_name FROM employees WHERE salary > 10000 ORDER BY last_name; enums NumTab; names NameTab; BEGIN SELECT employee_id, last_name BULK COLLECT INTO enums, names FROM employees ORDER BY employee_id; OPEN c1; LOOP FETCH c1 BULK COLLECT INTO enums, names LIMIT 10; EXIT WHEN names.COUNT = 0; do_something(); END LOOP; CLOSE c1; DELETE FROM emp_temp WHERE department_id = 30 RETURNING employee_id, last_name BULK COLLECT INTO enums, names; END;
      
      









forallサイクル










使用例
 DECLARE TYPE NumList IS TABLE OF NUMBER; depts NumList := NumList(10, 20, 30); TYPE enum_t IS TABLE OF employees.employee_id%TYPE; e_ids enum_t; TYPE dept_t IS TABLE OF employees.department_id%TYPE; d_ids dept_t; BEGIN FORALL j IN depts.FIRST .. depts.LAST DELETE FROM emp_temp WHERE department_id = depts(j) RETURNING employee_id, department_id BULK COLLECT INTO e_ids, d_ids; END;
      
      









forallの例外






収集の例外






例外をスローする状況の例
 DECLARE TYPE NumList IS TABLE OF NUMBER; nums NumList; BEGIN nums(1) := 1; -- raises COLLECTION_IS_NULL nums := NumList(1, 2); nums(NULL) := 3; -- raises VALUE_ERROR nums(0) := 3; -- raises SUBSCRIPT_BEYOND_COUNT nums(3) := 3; --raises SUBSCRIPT_OUTSIDE_LIMIT nums.Delete(1); IF nums(1) = 1 THEN ... -- raises NO_DATA_FOUND END;
      
      









DBMS_SESSION.FREE_UNUSED_USER_MEMORY








その場合、メモリを解放する必要があります。





使用例
 CREATE PACKAGE foobar type number_idx_tbl is table of number indexed by binary_integer; store1_table number_idx_tbl; -- PL/SQL indexed table store2_table number_idx_tbl; -- PL/SQL indexed table store3_table number_idx_tbl; -- PL/SQL indexed table ... END; -- end of foobar DECLARE ... empty_table number_idx_tbl; -- uninitialized ("empty") version BEGIN FOR i in 1..1000000 loop store1_table(i) := i; -- load data END LOOP; ... store1_table := empty_table; -- "truncate" the indexed table ... - dbms_session.free_unused_user_memory; -- give memory back to system store1_table(1) := 100; -- index tables still declared; store2_table(2) := 200; -- but truncated. ... END;
      
      









この記事の執筆に基づいた講義のビデオ録画:







Oracleのトピックに関する他の多くのビデオは、このチャンネルで見つけることができます。

www.youtube.com/c/MoscowDevelopmentTeam



その他のOracleの記事



Oracleのトリガーについて



All Articles