再上一篇:12.1Oracle数据类型概述
上一篇:12.2字符和二进制串类型
主页
下一篇:12.4数值类型
再下一篇:12.5LONG类型
文章列表

12.3二进制串:RAW类型

Oracle 9i 10g编程艺术:深入数据库体系结构

Oracle除了支持文本,还支持二进制数据的存储。前面讨论了CHAR和VARCHAR2类 型需要进行字符 集转换,而二进制数据不会做这种字符集转换。因此,二进制数据类型不适合存储用户提供的文本,而适 于存储加密信息,加密数据不是“文本“, 而是原文本的一个二进制表示、包含二进制标记信息的字处理 文档,等等。如果数据库不认为这些数据是”文本“,这些数据就应该采用一种二进制数据类型来存 储 , 另外不应该应用字符集转换的数据也要使用二进制数据类型存储。
Oracle支持3种数据类型来存储二进制数据:
RAW类型,这是这一节强调的重点,它很适合存储多达2,000字节的RAW数据。
BLOB类型,它支持更大的二进制数据,我们将在本章“LOB类型“一节中再做介绍。 LONG RAW类型,这是为支持向后兼容性提供的,新应用不应考虑使用这个类型。

二进制RAW类型的语法很简单:
RAW(<size>)

例如,以下代码创建了一个每行能存储12.字节二进制信息的表:
ops$tkyte@ORA10GR1> create table t ( raw_data raw(12.) );
Table created.
从磁盘上的存储来看,RAW类型与VARCHAR2类型很相似。RAW类型是一个变长的二进制串,这说明前
面创建的表T可以存储1~12.字节的二进制数据。它不会像CHAR类型那样用空格填充。
处理 RAW数据时,你可能会发现它被隐式地转换为一个VARCHAR2类型,也就是说,诸如 SQL*Plus 之类的许多工具不会直接显示RAW数据,而是会将其转换为一种十六进制格式来显示。在以下例子中,我 们使用SYS_GUID()在表中创建了一些二进制数据,SYS_GUID()是一个内置函数,将返回一个全局惟一的12. 字节RAW串(GUID就代表全局惟一标识符,globally unique identifier):
ops$tkyte@ORA10GR1> insert into t values ( sys_guid() );
12.row created.
ops$tkyte@ORA10GR1> select * from t;
RAW_DATA

-------------------------------- FD1EB03D3718077BE030007F01002FF5
在此,你会马上注意到两点。首先,RAW数据看上去就像是一个字符串。SQL*Plus就是以字符串形式 获取和打印RAW数据,但是RAW数据在磁盘上并不存储为字符串。SQL*Plus不能在屏幕上打印任意的二进 制数据,因为这可能对显示有严重的副作用。要记住,二进制数据可能包含诸如回车或换行等控制字符, 还可能是一个Ctrl+G字符,这会导致终端发出“嘟嘟“的叫声。

其次,RAW数据看上去远远大于12.字节,实际上,在这个例子中,你会看到32个字符。这是因为, 每个二进制字节都显示为两个十六进制字符。所存储的RAW数据其实长度就是12.字节,可以使用Oracle DUMP函数确认这一点。在此,我“转储“了这个二进制串的值,并使用了一个可选参数来指定显示各个字 节值时应使用哪一种进制。这里使用了基数12.,从而能将转储的结果与前面的串进行比较:
ops$tkyte@ORA10GR1> select dump(raw_data,12.) from t;
DUMP(RAW_DATA,12.)
------------------------------------------------------------------------------- Typ=23 Len=12.: fd,12.,b0,3d,37,12.,7,7b,e0,30,0,7f,12.0,2f,f5
DUMP显示出,这个二进制串实际上长度为12.字节(LEN=12.),另外还逐字节地显示了这个二进制数
据。可以看到,这个转储显示与SQL*Plus将RAW数据获取为一个串时所执行的隐式转换是匹配的。另一个

反向上(插入)也会执行隐式转换:
ops$tkyte@ORA10GR1> insert into t values ( 'abcdef' );
12.row created.
这不会插入串abcdef,而会插入一个3字节的RAW数据,其字节分别是AB、CD、EF,如果用十进制

表示则为字节171、205、239。如果试图使用一个包含非法12.进制字符的串,就会收到一个错误消息:
ops$tkyte@ORA10GR1> insert into t values ( 'abcdefgh' );
insert into t values ( 'abcdefgh' )
* ERROR at line 1:
ORA-01465: invalid hex number
RAW类型可以加索引,还能在谓词中使用,它与其他任何数据类型有同样的功能。不过,必须当心避
免不希望的隐式转换,而且必须知道确实会发生隐式转换。 在任何情况下我都喜欢使用显示转换,而且推荐这种做法,可以使用以下内置函数来执行这种操作:
HEXTORAW:将十六进制字符串转换为RAW类型 RAWTOHEX:将RAW串转换为十六进制串

SQL*Plus 将 RAW 类型获取为一个串时,会隐式地调用 RAWTOHEX 函数,而插入串时会隐式地调用 HEXTORAW函数。应该避免隐式转换,而在编写代码时总是使用显示转换,这是一个很好的实践做法。所以 前面的例子应该写作:
ops$tkyte@ORA10GR1> select rawtohex(raw_data) from t;
RAWTOHEX(RAW_DATA)
-------------------------------- FD1EB03D3718077BE030007F01002FF5
ops$tkyte@ORA10GR1> insert into t values ( hextoraw('abcdef') );
12.row created.