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。