如何通过Oracle数据类型的代码确定其字符串值?

如何通过Oracle数据类型的代码确定其字符串值?,oracle,plsql,database,Oracle,Plsql,Database,我使用DBMS_SQL.Descripte_COLUMNS过程来标识SELECT查询的结果集中的列所使用的数据类型。但不幸的是,通过这种方式,我只能得到Oracle数据类型record.col_type-1、8、12等的代码 因此,我想知道,如何轻松地获得与返回的数据类型代码(即VARCHAR2、LONG、DATE等)等效的字符串,而不是其数字代码?使用ANYDATA.GetTypeName 下面是一个带有一些解释和示例的链接: 我引述: SQL> DECLARE 2 v_an

我使用DBMS_SQL.Descripte_COLUMNS过程来标识SELECT查询的结果集中的列所使用的数据类型。但不幸的是,通过这种方式,我只能得到Oracle数据类型record.col_type-1、8、12等的代码

因此,我想知道,如何轻松地获得与返回的数据类型代码(即VARCHAR2、LONG、DATE等)等效的字符串,而不是其数字代码?

使用ANYDATA.GetTypeName

下面是一个带有一些解释和示例的链接:

我引述:

SQL> DECLARE
  2     v_anydata  ANYDATA := ANYDATA.ConvertVarchar2('String');
  3     v_typename VARCHAR2(128);
  4  BEGIN
  5     v_typename := v_anydata.GetTypeName();
  6     DBMS_OUTPUT.PUT_LINE('Type of ANYDATA instance is [' || v_typename || ']');
  7  END;
  8  /

Type of ANYDATA instance is [SYS.VARCHAR2]

PL/SQL procedure successfully completed.

以下是。

查看我的11gr2中的DBMS\u类型包:

select text from all_source
where owner='SYS'
and name='DBMS_TYPES'
and type='PACKAGE';

PACKAGE dbms_types AS

  TYPECODE_DATE            PLS_INTEGER :=  12;

  TYPECODE_NUMBER          PLS_INTEGER :=   2;

  TYPECODE_RAW             PLS_INTEGER :=  95;

  TYPECODE_CHAR            PLS_INTEGER :=  96;

  TYPECODE_VARCHAR2        PLS_INTEGER :=   9;

  TYPECODE_VARCHAR         PLS_INTEGER :=   1;

  TYPECODE_MLSLABEL        PLS_INTEGER := 105;

  TYPECODE_BLOB            PLS_INTEGER := 113;

  TYPECODE_BFILE           PLS_INTEGER := 114;

  TYPECODE_CLOB            PLS_INTEGER := 112;

  TYPECODE_CFILE           PLS_INTEGER := 115;

  TYPECODE_TIMESTAMP       PLS_INTEGER := 187;

  TYPECODE_TIMESTAMP_TZ    PLS_INTEGER := 188;

  TYPECODE_TIMESTAMP_LTZ   PLS_INTEGER := 232;

  TYPECODE_INTERVAL_YM     PLS_INTEGER := 189;

  TYPECODE_INTERVAL_DS     PLS_INTEGER := 190;



  TYPECODE_REF             PLS_INTEGER := 110;

  TYPECODE_OBJECT          PLS_INTEGER := 108;

  TYPECODE_VARRAY          PLS_INTEGER := 247;            /* COLLECTION TYPE */

  TYPECODE_TABLE           PLS_INTEGER := 248;            /* COLLECTION TYPE */

  TYPECODE_NAMEDCOLLECTION PLS_INTEGER := 122;

  TYPECODE_OPAQUE          PLS_INTEGER := 58;                 /* OPAQUE TYPE */



  /* NOTE: These typecodes are for use in AnyData api only and are short forms

     for the corresponding char typecodes with a charset form of SQLCS_NCHAR.

  */

  TYPECODE_NCHAR           PLS_INTEGER := 286;

  TYPECODE_NVARCHAR2       PLS_INTEGER := 287;

  TYPECODE_NCLOB           PLS_INTEGER := 288;



  /* Typecodes for Binary Float, Binary Double and Urowid. */

  TYPECODE_BFLOAT          PLS_INTEGER := 100;

  TYPECODE_BDOUBLE         PLS_INTEGER := 101;

  TYPECODE_UROWID          PLS_INTEGER := 104;



  SUCCESS                  PLS_INTEGER := 0;

  NO_DATA                  PLS_INTEGER := 100;

还请注意,109是一个用户定义的类型,您可能需要使用descripe\u COLUMNS3来代替。

这是一个稍微笨拙的解决方案,但是您可以使用CASE语句来查找数据类型描述

case record.col_type
  when dbms_types.TYPECODE_DATE then 'DATE'             
  when dbms_types.TYPECODE_NUMBER then 'NUMBER'           
  when dbms_types.TYPECODE_RAW then 'RAW'              
  when dbms_types.TYPECODE_CHAR then 'CHAR'             
  when dbms_types.TYPECODE_VARCHAR2 then 'VARCHAR2'         
  when dbms_types.TYPECODE_VARCHAR then 'VARCHAR'          
  when dbms_types.TYPECODE_MLSLABEL then 'MLSLABEL'         
  when dbms_types.TYPECODE_BLOB then 'BLOB'             
  when dbms_types.TYPECODE_BFILE then 'BFILE'            
  when dbms_types.TYPECODE_CLOB then 'CLOB'              
  when dbms_types.TYPECODE_CFILE then 'CFILE'            
  when dbms_types.TYPECODE_TIMESTAMP then 'TIMESTAMP'        
  when dbms_types.TYPECODE_TIMESTAMP_TZ then 'TIMESTAMP_TZ'     
  when dbms_types.TYPECODE_TIMESTAMP_LTZ then 'TIMESTAMP_LTZ'    
  when dbms_types.TYPECODE_INTERVAL_YM then 'INTERVAL_YM'      
  when dbms_types.TYPECODE_INTERVAL_DS then 'INTERVAL_DS'      
  when dbms_types.TYPECODE_REF then 'REF'              
  when dbms_types.TYPECODE_OBJECT then 'OBJECT'           
  when dbms_types.TYPECODE_VARRAY then 'VARRAY'                       
  when dbms_types.TYPECODE_TABLE then 'TABLE'                        
  when dbms_types.TYPECODE_NAMEDCOLLECTION then 'NAMEDCOLLECTION'  
  when dbms_types.TYPECODE_OPAQUE then 'OPAQUE'                            
  when dbms_types.TYPECODE_NCHAR then 'NCHAR'            
  when dbms_types.TYPECODE_NVARCHAR2 then 'NVARCHAR2'       
  when dbms_types.TYPECODE_NCLOB then 'NCLOB'                  
  when dbms_types.TYPECODE_BFLOAT then 'BFLOAT'           
  when dbms_types.TYPECODE_BDOUBLE then 'BDOUBLE'          
  when dbms_types.TYPECODE_UROWID then 'UROWID'              
end case
要获取该值,应查询数据字典。

尝试:

select 
   distinct
   c.type# type_code,
   decode(c.type#, 1, decode(c.charsetform, 2, 'NVARCHAR2', 'VARCHAR2'),
                   2, decode(c.scale, null, decode(c.precision#, null, 'NUMBER', 'FLOAT'), 'NUMBER'),
                   8, 'LONG',
                   9, decode(c.charsetform, 2, 'NCHAR VARYING', 'VARCHAR'),
                   12, 'DATE',
                   23, 'RAW', 24, 'LONG RAW',
                   69, 'ROWID',
                   96, decode(c.charsetform, 2, 'NCHAR', 'CHAR'),
                   100, 'BINARY_FLOAT',
                   101, 'BINARY_DOUBLE',
                   105, 'MLSLABEL',
                   106, 'MLSLABEL',
                   111, 'REF',
                   112, decode(c.charsetform, 2, 'NCLOB', 'CLOB'),
                   113, 'BLOB', 114, 'BFILE', 115, 'CFILE',
                   121, 'USER_TYPE',
                   122, 'USER_TYPE',
                   123, 'USER_TYPE',
                   178, 'TIME(' ||c.scale|| ')',
                   179, 'TIME(' ||c.scale|| ')' || ' WITH TIME ZONE',
                   180, 'TIMESTAMP(' ||c.scale|| ')',
                   181, 'TIMESTAMP(' ||c.scale|| ')'||' WITH TIME ZONE',
                   231, 'TIMESTAMP(' ||c.scale|| ')'||' WITH LOCAL TIME ZONE',
                   182, 'INTERVAL YEAR(' ||c.precision#||') TO MONTH',
                   183, 'INTERVAL DAY(' ||c.precision#||') TO SECOND(' ||
                         c.scale || ')',
                   208, 'UROWID',
                   'UNDEFINED') type_name from sys.col$ c order by c.type#;

这个解决方案看起来很有趣,但是您能解释一下,我如何为某个SQL查询的每一列设置ANYDATA变量的类型名?也就是说,我需要创建一个过程,将SQL查询作为输入参数,并将此查询的每一列的字符串数据类型名称集合作为输出参数。有没有可能在ANYDATA的帮助下实现?查看我添加的基于查询的示例的链接。感谢您提供的链接,它提供了非常丰富的信息。我会用任何数据尝试这样的解决方案。谢谢你的回答,我将结合@tbone的建议尝试这个解决方案:当DBMS_类型时,case record.col_type.TYPECODE_VARCHAR然后当DBMS_类型时'VARCHAR2_type.NUMBER然后'NUMBER_type'等等。一些整数值不在列表中,比如180表示时间戳,183表示间隔。看起来有些类型有多个ID。在做了一些测试后发现了它。找不到关于它的任何文档。Oracle版本是12.2,但sys.col$给了我们另一组ID,我们可以将它们与DBMS_类型中的ID结合起来,以获得更多类型。从列$;=115462从列$;=中选择countdistinct type nvals24在组顺序中选择listaggcol_类型,,,按col_类型col_类型从col$;中选择不同类型col_类型1、2、8、12、23、24、25、29、58、69、96、100、101、111、112、113、121、122、123、180、181、183、208、231。有人能给我解释一下为什么其中一些与手册中的不同吗?另外,从SYS.DBA_选项卡中的内容\u COLS_V$Strange…查询以从SYS包源代码中获取所有列类型代码:选择regexp_substrtext,'^.*PLS_INTEGER:=\s*\d+;.*$',1,1,NULL,1作为类型代码,regexp_substrtext,“^.*TYPECODE_[^]+.*$”,1,1,NULL,1作为类型名称,来自所有源,其中owner='SYS'和name='DBMS_TYPES'以及type='PACKAGE',以及类似“%TYPECODE%”的文本:=%;%订购人编号键入代码