long long类型上限_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列只是为了保证向后兼容性。

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子句中引用,也不能在使用了         如VARCHAR2、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类型。

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类型的子串:

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),这个包会以所有者的权限来运行,这样一来,它就只能看到包所有者能看到的数据,这可能不包括允许调用者看到的数据集。

函数SUBSTR_OF的基本思想是取一个查询,这个查询最多只选择一行和一列:即我们感兴趣的LONG值。如果需要,SUBSTR_OF会解析这个查询,为之绑定输入,并通过查询获取结果,返回LONG值中必要的部分。

包体(实现)最前面声明了两个全局变量。G_CURSOR变量保证一个持久游标在会话期间一直打开。这是为了避免反复打开和关闭游标,并避免不必要地过多解析SQL。第二个全局变量G_QUERY用于记住这个包中已解析的上一个SQL查询的文本。只要查询保持不变,就只需将其解析一次。因此,即使一个查询中查询了5,000行,只要我们传入这个函数的SQL查询不变,就只会有一个解析调用:

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。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值