web-dev-qa-db-ja.com

Oracleの匿名のTABLEまたはVARRAYタイプ

Oracleでは、このような構成を作成したい場合があります

SELECT * FROM TABLE(STRINGS('a', 'b', 'c'))
SELECT * FROM TABLE(NUMBERS(1, 2, 3))

明らかに、私は上記のために私自身のタイプを宣言することができます。 TABLEVARRAYのどちらかを選択できます。例えば:

CREATE TYPE STRINGS AS TABLE OF VARCHAR2(100);
CREATE TYPE NUMBERS AS VARRAY(100) OF NUMBER(10);

この特定のケースでは、別の解決策は次のようなものを書くことです

SELECT 'a' FROM DUAL UNION ALL
SELECT 'b' FROM DUAL UNION ALL
SELECT 'c' FROM DUAL

しかし、実際にはTABLE/VARRAY型が必要になるもっと複雑な例があるかもしれません。では、必要な許可がない可能性があるために型を作成できない不明なシステムでSQLが実行されている場合はどうなりますか?

私の質問は次のとおりです: Oracleは、任意のOracleインスタンスで使用可能な「匿名」のTABLE/VARRAYタイプを知っていますか? Postgres/H2/HSQLDBの単純なARRAYタイプに似ていますか?

[〜#〜] update [〜#〜]:これが関係する場合、私は主にJavaからこのSQLを実行しています。 PL/SQLを説明する必要はありません。私は、匿名のSQL配列型(つまり、「匿名」スタンドアロンの格納型)を探しています。それらがまったく存在しない場合、答えは[〜#〜] no [〜#〜]です。

19
Lukas Eder

SQLテーブルとVARRAYタイプ

興味深い解決策がユーザーによって与えられました ここではAPC 。この質問の将来の読者にとって、このクエリが私が本当に興味を持っているものを提供するのを見るのは興味深いかもしれません:

_select coll_type, elem_type_name, type_name, length, upper_bound
from all_coll_types
where owner = 'SYS'
and elem_type_name IN ('VARCHAR2', 'NUMBER')
order by coll_type, elem_type_name, type_name;
_

結果として(Oracle 11gの場合):

_+-------------+--------------+----------------------+------+-----------+
|COLL_TYPE    |ELEM_TYPE_NAME|TYPE_NAME             |LENGTH|UPPER_BOUND|
+-------------+--------------+----------------------+------+-----------+
|TABLE        |NUMBER        |KU$_OBJNUMSET         |{null}|     {null}|
|TABLE        |NUMBER        |KU$_XMLCOLSET_T       |{null}|     {null}|
|TABLE        |NUMBER        |ORA_MINING_NUMBER_NT  |{null}|     {null}|
|TABLE        |VARCHAR2      |DBMS_AW$_COLUMNLIST_T |   100|     {null}|
|TABLE        |VARCHAR2      |DBMS_DEBUG_VC2COLL    |  1000|     {null}|
|TABLE        |VARCHAR2      |HSBLKNAMLST           |    30|     {null}|
|TABLE        |VARCHAR2      |KU$_VCNT              |  4000|     {null}|
|TABLE        |VARCHAR2      |ORA_MINING_VARCHAR2_NT|  4000|     {null}|
|VARYING ARRAY|NUMBER        |AWRRPT_NUM_ARY        |{null}|         30|
|VARYING ARRAY|NUMBER        |JDM_NUM_VALS          |{null}|        999|
|VARYING ARRAY|NUMBER        |ODCIGRANULELIST       |{null}|      65535|
|VARYING ARRAY|NUMBER        |ODCINUMBERLIST        |{null}|      32767|
|VARYING ARRAY|NUMBER        |SQL_OBJECTS           |{null}|       2000|
|VARYING ARRAY|NUMBER        |TABLESPACE_LIST       |{null}|      64000|
|VARYING ARRAY|VARCHAR2      |AQ$_JMS_NAMEARRAY     |   200|       1024|
|VARYING ARRAY|VARCHAR2      |AQ$_MIDARRAY          |    32|       1024|
|VARYING ARRAY|VARCHAR2      |AWRRPT_VCH_ARY        |    80|         30|
|VARYING ARRAY|VARCHAR2      |DBMSOUTPUT_LINESARRAY | 32767| 2147483647|
|VARYING ARRAY|VARCHAR2      |DBMS_XS_ROLELIST      |  1024|       4096|
|VARYING ARRAY|VARCHAR2      |FLASHBACKTBLIST       |    30|        100|
|VARYING ARRAY|VARCHAR2      |HSBLKVALARY           |  4000|        250|
|VARYING ARRAY|VARCHAR2      |JDM_ATTR_NAMES        |    60|        999|
|VARYING ARRAY|VARCHAR2      |JDM_STR_VALS          |  4000|        999|
|VARYING ARRAY|VARCHAR2      |KU$_DROPCOLLIST       |  4000|       1000|
|VARYING ARRAY|VARCHAR2      |KUPC$_LOBPIECES       |  4000|       4000|
|VARYING ARRAY|VARCHAR2      |ODCIRIDLIST           |  5072|      32767|
|VARYING ARRAY|VARCHAR2      |ODCIVARCHAR2LIST      |  4000|      32767|
|VARYING ARRAY|VARCHAR2      |RE$NAME_ARRAY         |    30|       1024|
|VARYING ARRAY|VARCHAR2      |RE$RULE_LIST          |    65|       1024|
|VARYING ARRAY|VARCHAR2      |SQLPROF_ATTR          |   500|       2000|
|VARYING ARRAY|VARCHAR2      |TXNAME_ARRAY          |   256|        100|
+-------------+--------------+----------------------+------+-----------+
_

_ORA_MINING_NUMBER_NT_と_ORA_MINING_VARCHAR2_NT_が私のニーズに最適であるように見えます。

PL/SQLインデックス付き配列タイプ

Oracle12cおよびPL/SQLを使用している場合は、_DBMS_SQL_タイプのいずれかを使用する可能性もあります。これは、TABLE(..)コンストラクタを使用してネスト解除できます。がある:

  • _DBMS_SQL.CLOB_TABLE_
  • _DBMS_SQL.BINARY_FLOAT_TABLE_
  • _DBMS_SQL.BINARY_DOUBLE_TABLE_
  • _DBMS_SQL.BLOB_TABLE_
  • _DBMS_SQL.BFILE_TABLE_
  • _DBMS_SQL.DATE_TABLE_
  • _DBMS_SQL.NUMBER_TABLE_
  • _DBMS_SQL.UROWID_TABLE_
  • _DBMS_SQL.VARCHAR2_TABLE_
  • _DBMS_SQL.TIME_TABLE_
  • _DBMS_SQL.TIME_WITH_TIME_ZONE_TABLE_
  • _DBMS_SQL.TIMESTAMP_TABLE_
  • _DBMS_SQL.TIMESTAMP_WITH_LTZ_TABLE_
  • _DBMS_SQL.TIMESTAMP_WITH_TIME_ZONE_TABLE_
  • _DBMS_SQL.INTERVAL_DAY_TO_SECOND_TABLE_
  • _DBMS_SQL.INTERVAL_YEAR_TO_MONTH_TABLE_
15
Lukas Eder

SYSスキーマを明示的に参照することを恐れないのであれば、いくつかあります。これが私がよく使うものです(odcivarchar2listはあまりメモリを消費しないので、それほど多くはありません。文字列の場合はdbms_debug_vc2collを好みます)。

SQL> desc sys.odcinumberlist
 sys.odcinumberlist VARRAY(32767) OF NUMBER

SQL> desc sys.odcivarchar2list
 sys.odcivarchar2list VARRAY(32767) OF VARCHAR2(4000)

SQL> desc sys.ODCIDATELIST
 sys.ODCIDATELIST VARRAY(32767) OF DATE

SQL> desc sys.dbms_debug_vc2coll
 sys.dbms_debug_vc2coll TABLE OF VARCHAR2(1000)

SQL> 

ただし、それらがニーズに対して十分でない場合は、このクエリを実行してさらにいくつかを見つけてください。

select type_name
       , owner
from all_types
where typecode = 'COLLECTION'
and owner != user
/

もちろん、この結果はデー​​タベースごとに異なります。たとえば、私のデータベースのコレクションの多くはXDBによって所有されており、すべてのシステムにそれがインストールされているわけではありません。この回答の上部にリストした4つは、9iR2以降(およびおそらく初期)のすべてのデータベースで使用できるはずですが、以前のバージョンで常に文書化されているわけではありません。


「ALL_COLL_TYPESは、適切なタイプを見つけるためのさらに優れた辞書ビューのように見えることに注意してください」

それは良い点です。 COLL_TYPEでフィルタリングして、VARRAYを選別することもできます。そのビューは10gに導入されましたが、ALL_TYPESは9iで使用可能でした。 Oracleのほとんどのものと同様に、バージョンが遅いほど、より多くの機能があります。

19
APC

あなたの質問は非常に一般的です-基本的に、次のような匿名のPL/SQLブロックで明示的なCREATE TYPEなしでこれら(VARARRAY/TABLE)を使用できます。

DECLARE
    TYPE genres IS VARRAY(4) OF book_genre.genre_name%TYPE;
    Fiction_genres genres;
    TYPE phone_no_tab IS VARRAY(6) OF VARCHAR2(20) ;
    phone_nos phone_no_tab;
BEGIN
    fiction_genres := genres('MYSTERY','SUSPENSE', 'ROMANCE','HORROR');
    phone_nos := phone_no_tab();
    phone_nos.EXTEND(2);
    phone_nos(1) := '0117 942 2508';
END;

またはこのように

declare

  TYPE auftrag_table_typ IS TABLE OF auftrag%ROWTYPE
          INDEX BY BINARY_INTEGER;

  auftrag_table auftrag_table_typ;

  v_index BINARY_INTEGER;

begin

  v_index := auftrag_table.first;

  while v_index is not NULL loop

    // do something with auftrag_table(v_index)

    v_index := auftrag_table.next (v_index);

  end loop;

end; 

Oracleのリファレンスについては、 http://docs.Oracle.com/cd/E11882_01/appdev.112/e25519/composites.htm を参照してください。これによると、このようなVARARRAYおよび/またはTABLEDECLAREdであるか、CREATE TYPEを介して作成される必要があるため、「匿名のVARARRAY/TABLE」のようなものはありません。

2
Yahia