oracle数值类型--LONG类型

Oracle中的LONG类型有两种:
LONG文本类型,能存储2GB的文本。与VARCHAR2或CHAR类型同样,存储在LONG类型中的文本要进行字符集转换。
LONG RAW类型,能存储2GB的原始二进制数据(不用进行字符集转换的数据)。
在此并不解释如何使用LONG类型,而是会解释为何你不但愿在应用中使用LONG(或LONG RAW)类型。首先要注意的是,Oracle文档在如何处理LONG类型方面描述得很明确。Oracle SQL Reference手册指出:
不要建立带LONG列的表,而应该使用LOB列(CLOB、NCLOB、BLOB)。支持LONG列只是为了保证向后兼容性。sql

1 LONG和LONG RAW类型的限制

 

LONG/LONG RAW类型                                         CLOB/BLOB类型
每一个表中只能有一个LONG或LONG RAW列         每一个表能够有最多12.000个CLOB或BLOB类型的列
定义用户定义的类型时,不能有LONG/LONG     用户定义的类型完成可使用CLOB和BLOB类型
RAW类型的属性
不能在WHERE子句中引用LONG类型                 WHERE子句中能够引用LOB类型,并且DBMS_LOB包
                                                                        中提供了大量函数来处理LOB类型
除了NOT NULL以外,完整性约束中不能引用     完整性约束中能够引用LOB类型
LONG类型
LONG类型不支持分布式事务                                 LOB确实支持分布式事务
LONG类型不能使用基本或高级复制技术来复制     LOB彻底支持复制
LONG列不能在GROUP BY、ORDER BY或             只要对LOB应用一个函数,将其转换为一个标量SQL类型,数据库

CONNECT BY子句中引用,也不能在使用了         如VARCHAR二、NUMBER或DATE,LOB就能够出如今
DISTINCT、UNIQUE、INTERSECT、MINUS     这些子句中
或UNION的查询中使用
PL/SQL函数/过程不能接受LONG类型的输入         PL/SQL能够充分处理LOB类型
SQL内置函数不能应用于LONG列(如SUBSTR)     SQL函数能够应用于LOB类型
CREATE TABLE AS SELECT语句中不能使用             LOB支持CREATE TABLE AS SELECT
LONG类型
在包含LONG类型的表上不能使用ALTER TABLE MOVE         能够移动包含LOB的表安全

若是表中有一个LONG列,那么不少事情都不能作。对于全部新的应用,甚至根本不应考虑使用LONG类型。相反,应该使用适当的LOB类型。对于现有的应用,若是受到表12.-2所列的某个限制,就应该认真地考虑将LONG类型转换为相应的LOB类型。因为已经作了充分考虑来提供向后兼容性,因此编写为使用LONG类型的应用也能透明地使用LOB类型。app

 

2 处理遗留的LONG类型

“那如何考虑Oracle中的数据字典呢?“数据字典中散布着LONG列,这就使得字典列的使用很成问题。例如,不能使用SQL搜索ALL_VIEWS字典视图来找出包含文本HELLO的全部视图:分布式

scott@ORCL>select *
  2  from all_views
  3  where text like '%HELLO%';
where text like '%HELLO%'
      *
第 3 行出现错误:
ORA-00932: 数据类型不一致: 应为 NUMBER, 但却得到 LONG

这个问题并不仅是ALL_VIEWS视图才有,许多视图都存在一样的问题:函数

scott@ORCL>select table_name, column_name
  2  from dba_tab_columns
  3  where data_type in ( 'LONG', 'LONG RAW' )
  4  and owner = 'SYS'
  5  and table_name like 'DBA%';

TABLE_NAME                                                   COLUMN_NAME
------------------------------------------------------------ -------------------
-----------------------------------------
DBA_ADVISOR_SQLPLANS                                         OTHER
DBA_ARGUMENTS                                                DEFAULT_VALUE
DBA_CLUSTER_HASH_EXPRESSIONS                                 HASH_EXPRESSION
DBA_CONSTRAINTS                                              SEARCH_CONDITION
DBA_IND_EXPRESSIONS                                          COLUMN_EXPRESSION
DBA_IND_PARTITIONS                                           HIGH_VALUE
DBA_IND_SUBPARTITIONS                                        HIGH_VALUE
DBA_MVIEWS                                                   QUERY
DBA_MVIEW_AGGREGATES                                         MEASURE
DBA_MVIEW_ANALYSIS                                           QUERY
DBA_NESTED_TABLE_COLS                                        DATA_DEFAULT
DBA_OUTLINES                                                 SQL_TEXT
DBA_REGISTERED_MVIEWS                                        QUERY_TXT
DBA_REGISTERED_SNAPSHOTS                                     QUERY_TXT
DBA_SNAPSHOTS                                                QUERY
DBA_SQLSET_PLANS                                             OTHER
DBA_SQLTUNE_PLANS                                            OTHER
DBA_SUBPARTITION_TEMPLATES                                   HIGH_BOUND
DBA_SUMMARIES                                                QUERY
DBA_SUMMARY_AGGREGATES                                       MEASURE
DBA_TAB_COLS                                                 DATA_DEFAULT
DBA_TAB_COLUMNS                                              DATA_DEFAULT
DBA_TAB_PARTITIONS                                           HIGH_VALUE
DBA_TAB_SUBPARTITIONS                                        HIGH_VALUE
DBA_TRIGGERS                                                 TRIGGER_BODY
DBA_VIEWS                                                    TEXT
DBA_VIEWS_AE                                                 TEXT

已选择27行。

若是你想在SQL中使用这些列,就须要将它们转换为一种对SQL友好的类型。可使用一个用户定义的函数来作到这一点。如下例子展现了如何使用一个LONG SUBSTR函数来达到这个目的,这个函数容许将任何4,000字节的LONG类型转换为一个VARCHAR2,以便用于SQL。完成后,就能执行如下查询。首先 如何获得一个LONG类型的子串:fetch

scott@ORCL>create or replace package long_help
  2  authid current_user
  3  as
  4  function substr_of
  5  ( p_query in varchar2,
  6  p_from in number,
  7  p_for in number,
  8  p_name1 in varchar2 default NULL,
  9  p_bind1 in varchar2 default NULL,
 10  p_name2 in varchar2 default NULL,
 11  p_bind2 in varchar2 default NULL,
 12  p_name3 in varchar2 default NULL,
 13  p_bind3 in varchar2 default NULL,
 14  p_name4 in varchar2 default NULL,
 15  p_bind4 in varchar2 default NULL )
 16  return varchar2;
 17  end;
 18  /

程序包已建立。

在第2行上 指定了AUTHID CURRENT_USER。 这使得这个包会做为调用者运行,拥有全部角色和权限。这一点很重要,缘由有两个。首先,咱们但愿数据库安全性不要受到破坏,这个包只返回容许咱们(调用 者)看到的列子串。其次,咱们但愿只在数据库中将这个包安装一次,就能一直使用它的功能;使用调用者权限能够保证这一点。若是咱们使用PL/SQL的默认安全模型(定义者权限,define right),这个包会以全部者的权限来运行,这样一来,它就只能看到包全部者能看到的数据,这可能不包括容许调用者看到的数据集。spa

函数SUBSTR_OF的基本思想是取一个查询,这个查询最多只选择一行和一列:即咱们感兴趣的LONG值。若是须要,SUBSTR_OF会解析这个查询,为之绑定输入,并经过查询获取结果,返回LONG值中必要的部分。
包体(实现)最前面声明了两个全局变量。G_CURSOR变量保证一个持久游标在会话期间一直打开。这是为了不反复打开和关闭游标,并避免没必要要地过多解析SQL。第二个全局变量G_QUERY用于记住这个包中已解析的上一个SQL查询的文本。只要查询保持不变,就只需将其解析一次。所以,即便一个查询中查询了5,000行,只要咱们传入这个函数的SQL查询不变,就只会有一个解析调用:code

scott@ORCL>create or replace package body long_help
  2  as
  3
  4  g_cursor number := dbms_sql.open_cursor;
  5  g_query varchar2(32765);
  6
  7  procedure bind_variable( p_name in varchar2, p_value in varchar2 )
  8
  9  is
 10  begin
 11     if ( p_name is not null )
 12     then
 13             dbms_sql.bind_variable( g_cursor, p_name, p_value );
 14     end if;
 15  end;
 16
 17  function substr_of
 18  ( p_query in varchar2,
 19     p_from in number,
 20     p_for in number,
 21     p_name1 in varchar2 default NULL,
 22     p_bind1 in varchar2 default NULL,
 23     p_name2 in varchar2 default NULL,
 24     p_bind2 in varchar2 default NULL,
 25     p_name3 in varchar2 default NULL,
 26     p_bind3 in varchar2 default NULL,
 27     p_name4 in varchar2 default NULL,
 28     p_bind4 in varchar2 default NULL )
 29  return varchar2
 30
 31  as
 32     l_buffer varchar2(4000);
 33     l_buffer_len number;
 34
 35  begin
 36             if ( nvl(p_from,0) <= 0 )
 37             then
 38                     raise_application_error
 39                     (-20002, 'From must be >= 1 (positive numbers)' );
 40             end if;
 41
 42             if ( nvl(p_for,0) not between 12 and 4000 )
 43             then
 44                     raise_application_error
 45                     (-20003, 'For must be between 12 and 4000' );
 46             end if;
 47
 48             if ( p_query <> g_query or g_query is NULL )
 49             then
 50                     if ( upper(trim(nvl(p_query,'x'))) not like 'SELECT%')
 51                     then
 52                             raise_application_error
 53                             (-20001, 'This must be a select only' );
 54                     end if;
 55                     dbms_sql.parse( g_cursor, p_query, dbms_sql.native );
 56                     g_query := p_query;
 57             end if;
 58
 59             bind_variable( p_name1, p_bind1 );
 60             bind_variable( p_name2, p_bind2 );
 61             bind_variable( p_name3, p_bind3 );
 62             bind_variable( p_name4, p_bind4 );
 63
 64             dbms_sql.define_column_long(g_cursor, 1);
 65             if (dbms_sql.execute_and_fetch(g_cursor)>0)
 66             then
 67                     dbms_sql.column_value_long
 68                     (g_cursor, 1, p_for, p_from-1,
 69                     l_buffer, l_buffer_len );
 70             end if;
 71     return l_buffer;
 72  end substr_of;
 73
 74  end;
 75  /

程序包体已建立。
scott@ORCL>select *
  2  from (
  3     select owner, view_name,
  4             long_help.substr_of( 'select text
  5             from dba_views
  6             where owner = :owner
  7             and view_name = :view_name',
  8             1, 4000,
  9             'owner', owner,
 10             'view_name', view_name ) substr_of_view_text
 11     from dba_views
 12     where owner = user
 13  )
 14  where upper(substr_of_view_text) like '%INNER%'
 15  /

未选定行
scott@ORCL>select *
  2  from (
  3     select table_owner, table_name, partition_name,
  4             long_help.substr_of
  5                     ( 'select high_value from all_tab_partitions
  6                     where table_owner = :o and table_name = :n and partition
_name = :p',
  7             1, 4000,
  8             'o', table_owner,
  9             'n', table_name,
 10             'p', partition_name ) high_value
 11     from all_tab_partitions
 12     where table_name = 'T'
 13     and table_owner = user
 14  )
 15  where high_value like '%2003%'
 16  /

未选定行

还有一种方法,可使用TO_LOB内置函数和一个全局临时表,将LONG或LONG RAW临时地转换为CLOB或BLOB。为此,PL/SQL过程能够以下:事务

Insert into global_temp_table ( blob_column )
select to_lob(long_raw_column) from t where...

这在偶尔须要处理单个LONG RAW值的应用中能很好地工做。不过,为此须要作的工做太多了。应该干脆将LONG RAW一次性转换为BLOB,而后处理BLOB。

相关文章
相关标签/搜索