在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是否知道"匿名"任何Oracle实例上可用的TABLE
/ VARRAY
类型?类似于Postgres / H2 / HSQLDB的简单ARRAY
类型?
UPDATE :我主要是从Java运行这个SQL,如果这是相关的。无需向我解释PL / SQL,我真的只是在寻找匿名SQL数组类型(即"匿名" 独立存储类型)。如果他们根本不存在,答案是 NO
答案 0 :(得分:19)
如果您不害怕明确引用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
/
当然,这个结果因数据库而异。例如,我的数据库中的很多colllections都归XDB所有,并不是每个系统都安装了。从9iR2(可能是早期版本)开始,每个数据库都应该提供我在本答案顶部列出的四个,尽管它们并不总是在早期版本中记录。
“请注意,ALL_COLL_TYPES似乎是一个更好的字典视图 找到合适的类型“
这是一个好点。我们还可以过滤COLL_TYPE以赢取VARRAY。该视图被引入10g,而ALL_TYPES可用于9i。与大多数Oracle一样,版本越晚,它的功能就越多。
答案 1 :(得分:15)
用户APC here提供了一个有趣的解决方案。对于这个问题的未来读者,可能有趣的是看到这个查询提供了我真正感兴趣的内容:
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
最符合我的需求。
如果使用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 :(得分:2)
您的问题很一般 - 基本上您可以在匿名PL / SQL块中使用这些(VARARRAY
/ TABLE
)而不使用明确的CREATE TYPE
:
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
”这样的内容。