Анонимный тип TABLE или VARRAY в Oracle - PullRequest
19 голосов
/ 09 января 2012

В Oracle я иногда хотел бы создавать такие конструкции, как эти

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

Очевидно, я могу объявить свои собственные типы для вышеперечисленного.Я могу выбирать между TABLE и VARRAY.Например:

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 "анонимный" TABLE / VARRAY типы, доступные в любом экземпляре Oracle?Аналогично простым ARRAY типам Postgres / H2 / HSQLDB?

UPDATE : я в основном запускаю этот SQL из Java, если это уместно.Мне не нужно объяснять PL / SQL, я просто ищу анонимные типы массивов SQL (т.е. «анонимные» автономные хранимые типы ).Если они вообще не существуют, ответ будет NO

Ответы [ 3 ]

19 голосов
/ 09 января 2012

Если вы не боитесь явной ссылки на схему 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, и не на каждой системе это будет установлено. Четыре, которые я перечислил в верхней части этого ответа, должны быть доступны в каждой базе данных начиная с 9iR2 (и, возможно, в начале), хотя они не всегда документированы в более ранних версиях.


"Обратите внимание, что ALL_COLL_TYPES выглядит даже лучше найти подходящие типы "

Это хороший момент. Мы также можем отфильтровать COLL_TYPE, чтобы отсеять VARRAY. Это представление было введено в 10g, тогда как ALL_TYPES был доступен в 9i. Как и в большинстве случаев Oracle, чем позже версия, тем больше у нее функциональности.

15 голосов
/ 09 января 2012

Типы таблиц и переменных SQL

Интересное решение предоставил пользователь 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 индексируемые типы массивов

При использовании Oracle 12c и 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
2 голосов
/ 09 января 2012

Ваш вопрос очень общий - в основном вы можете использовать их (VARARRAY / TABLE) без явного CREATE TYPE в анонимных блоках PL / SQL, например:

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 и / или TABLE должны быть DECLARE d или созданы с помощью CREATE TYPE, поэтому в AFAIK нет такой вещи, как "Аноним VARARRAY / TABLE".

...