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
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
“那如何考虑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。