精华内容
下载资源
问答
  • Oracle二进制类型和大对象类型基础

    千次阅读 2015-02-12 16:48:55
    Oracle二进制类型和大对象类型基础 2013-08-0813:35:47 我来说两句 作者:媛媛小译 收藏 我要投稿 Oracle二进制类型和大对象类型基础   一、类型区分    NCLOB 存储单字节的字符数据   CLOB 存储多...

    窗体顶端

    窗体底端

    Oracle二进制类型和大对象类型基础

    2013-08-0813:35:47     我来说两句       作者:媛媛小译

    收藏    我要投稿

    Oracle二进制类型和大对象类型基础

     

    一、类型区分 

     

    NCLOB 存储单字节的字符数据

     

    CLOB 存储多字节的字符数据 

     

    BFILE 存储OS文件系统中的二进制文件的指针,文件不存储在数据库里。 

     

    BLOB 存储二进制数据 

     

    RAW 存储定长二进制数据,需要定义长度,如:

    ?

    1

    create table t(s raw(2000);

     

     

    LONG RAW 存储可变长二进制数据 

     

    二、类型在数据库中的使用 

     

    ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    NCLOB

     

    create table t(id int,cont NCLOB);

     

    Insert into t(id,cont) values(1,’hello’);

     

    select * from t;

     

    ID CONT

     

    -------------------------

     

    1 hello

     

    CLOB 同NCLOB。

     

    BLOB 暂未找到能直接插入的值的方法。

     

    BFILE

     

    Conn lyy/lyy

     

    Create table bfiletable(id int,obj BFILE);

     

    Create or replace directory dir AS ‘d:\’;

     

    Conn / as sysdba

     

    Grant read directpry dir to lyy;

     

    Conn lyy/lyy Insert into bfiletable(id,obj) values(1,filename(‘DIR’,’1.jpg’));

     

    Select * from filetable;

     

    ID OBJ

     

    -------------------------------------------------

     

    1 filename(‘DIR’,’1.JPG’)

     

     

    RAW 

     

    Create table rawtable(id int,obj raw(2000));

     

    Insert into rawtable(id,obj) values(1, uti_raw.cast_to_raw(‘hello’));

     

    Select * from rawtable;

     

    ID OBJ

     

     -------------------------------------------------

     

     1 68656C6C6F

     

     

     

    LONG RAW

     

    Create table lrawtable(id int,obj long raw);

     

    Insert into lrawtable(id,obj) values(1, uti_raw.cast_to_raw(‘hello’));

     

    Select * from lrawtable;

     

    ID OBJ

     

    -------------------------------------------------

     

    1 6

     


    SQL> desc utl_raw
    FUNCTION CAST_TO_NVARCHAR2 RETURNS NVARCHAR2
    参数名称                      类型                   输入/输出默认值?
    ------------------------------ ----------------------- ------ --------
     R                             RAW                    IN
    FUNCTION CAST_TO_RAW RETURNS RAW
    参数名称                      类型                   输入/输出默认值?
    ------------------------------ ----------------------- ------ --------
     C                             VARCHAR2               IN
     
    CAST_TO_VARCHAR2 Function:
    Converts a RAW represented using n data bytes into VARCHAR2 with n data bytes

     

    CAST_TO_RAW Function
    Converts a VARCHAR2 represented using n data bytes into a RAW with n data bytes
     
    SQL> col name for a40;
    SQL> select utl_raw.cast_to_raw('甲骨文') name fromdual;

    NAME
    ----------------------------------------
    E794B2E9AAA8E69687

     

    SQL> select utl_raw.cast_to_varchar2('E794B2E9AAA8E69687') name  from dual;

    NAME
    ----------------------------------------
    甲骨文

     

    SQL> select dump('甲骨文' ,16) namefrom dual;

    NAME
    ----------------------------------------
    Typ=96 Len=9: e7,94,b2,e9,aa,a8,e6,96,87

    下面是常用到了两个函数:
    utl_raw.cast_to_raw([varchar2]);--将varchar2转换为raw类型
    utl_raw.cast_to_varchar2([raw]);--将raw转换为varchar2类型(是将raw数据类型的数据而不是其他数据类型的数据转换为varchar2类型?)

    展开全文
  • JAVA中,读取Oracle中二进制BLOB类型数据,出现乱码.. 如果BLOB是文本类型存储的就不会存在乱码 BLOB blob = (oracle.sql.BLOB)rs.getBlob("ys1"); try{ FileOutputStream outStream = new ...
  • :这是一种变长二进制数据类型,这说明采用这种数据类型存储的数据不会发生字符集转换。可以把它看作由数据库存储的信息的二进制字节串。这种类型最多可以存储2,000字节的信息。 NUMBER :这种数据类型能存储精度...

    1 Oracle数据类型概述

    CHAR:这是一个定长字符串会用空格填充来达到其最大长度。非null的CHAR(2) 总是包含2字节信息(使用了默认国家语言支持National Language Support,NLS设置)。CHAR字段最多可以存储2,000字节的信息。
    NCHAR:这是一个包含UNICODE格式数据的定长字符串。Unicode是一种对字符进行编码的通用方法,而不论使用的是何种计算机系统平台。有了NCHAR类型,就允许数据库中包含采用两种不同字符集的数据:使用数据库字符集的CHAR类型和使用国家字符集的NCHAR类型。非null的NCHAR(2)总是包含2个字符的信息(注意,在这方面,它与CHAR类型有所不同)。NCHAR字段最多可以存储2,000字节的信息。
    VARCHAR2:VARCHAR的同义词。这是一个变长字符串,与CHAR类型不同,它不会用空格填充至最大长度。VARCHAR2(12)可能包含0~12字节的信息(使用默认NLS设置)。VARCHAR2最多可以存储4,000字节的信息。
    NVARCHAR2:这是一个包含UNICODE格式数据的变长字符串。NVARCHAR2(12)可以包含0~12字符的信息。NVARCHAR2最多可以存储4,000字节的信息。
    RAW:这是一种变长二进制数据类型,这说明采用这种数据类型存储的数据不会发生字符集转换。可以把它看作由数据库存储的信息的二进制字节串。这种类型最多可以存储2,000字节的信息。
    NUMBER:这种数据类型能存储精度最多达38位的数字。每个数存储在一个变长字段中,其长度在0(尾部的NULL列就是0字节)~22字节之间。Oracle的NUMBER类型精度很高,远远高于许多编程语言中常规的FLOAT和DOUBLE类型。
    BINARY_FLOAT:这是Oracle 10g Release 1及以后版本中才有的一种新类型。它是一个32位单精度浮点数,可以支持至少6位精度,占用磁盘上5字节的存储空间。
    LONG:这种类型能存储最多2G的字符数据(2GB是指2千兆字节,而不是2千兆字符,因为在一个多字节字符集中,每个字符可能有多个字节)。由于LONG类型有许多限制,而且提供LONG类型只是为了保证向后兼容性,所以强烈建议新应用中不要使用LONG类型,而且在现有的应用中也要尽可能将LONG类型转换为CLOB类型
    LONG RAW:LONG RAW类型能存储多达2GB的二进制信息。由于LONG同样的原因,建议在将来的所有开发中都使用CLOB类型,另外现有的应用中也应尽可能将LONG RAW转换为BLOB类型。
    DATE:这是一个7字节的定宽日期/时间数据类型。总包含7个属性,包括:世纪、世纪中哪一年、月份、月中的哪一天、小时、分钟和秒。
    TIMESTAMP:这是一个7字节或12字节的定宽日期/时间数据类型。它与DATE数据类型不同,因为TIMESTAMP可以包含小数秒(fractional second);带小数秒的TIMESTAMP在小数点右边最多可以保留9位。
    TIMESTAMP WITH TIME ZONE:与前一种类型类似,这是一个12字节的定宽TIMESTAMP,不过它还提供了时区(TIME ZONE)支持。数据中会随TIMESTAMP存储有关时区的额外信息,所以原先插入的TIME ZONE会与数据一同保留。
    TIMESTAMP WITH LOCAL TIME ZONE:与TIMESTAMP类似,这是一种7字节或12.字节的定宽日期/时间数据类型;不过,这种类型对时区敏感(time zone sensitive)。如果在数据库中有修改,会参考数据中提供的TIME ZONE,根据数据库时区对数据中的日期/时间部分进行“规范化”。
    INTERVAL YEAR TO MONTH:这是一个5字节的定宽数据类型,用于存储一个时间段,这个类型将时段存储为年数和月数。可以在日期运算中使用这种时间间隔使一个DATE或TIMESTAMP类型增加或减少一段时间。
    INTERVAL DAY TO SECOND:这是一个12字节的定宽数据类型,用于存储一个时段,这个类型将时段存储为天/小时/分钟/秒数,还可以有最多9位的小数秒。
    BFILE:这种数据类型允许在数据库列中存储一个Oracle目录对象(操作系统目录的一个指针)和一个文件名,并读取这个文件。这实际上允许你以一种只读的方式访问数据库服务器上可用的操作系统文件,就好像它们存储在数据库表本身中一样。
    BLOB:在Oracle9i及以前的版本中,这种数据类型允许存储最多4GB的数据,在Oracle 10g及以后的版本中允许存储最多(4GB)×(数据库块大小)字节的数据。BLOB包含不需要进行字符集转换的“二进制“数据,适合存储电子表格、字处理文档、图像文件等。
    CLOB:允许存储最多(4GB)×(数据库块大小)字节的数据。CLOB包含要进行字符集转换的信息。很适合存储纯文本信息。
    NCLOB:允许存储最多(4GB)×(数据库块大小)字节的数据。NCLOB存储用数据库国家字符集编码的信息,这些信息要进行字符集转换。
    ROWID:ROWID实际上是数据库中一行的12字节地址。ROWID中编码有足够的信息,足以在磁盘上定位这一行,以及标识ROWID指向的对象(表等)。
    UROWID:UROWID是一个通用ROWID,用于表(如IOT和通过异构数据库网关访问的没有固定ROWID的表)。UROWID是行主键值的一种表示,因此,取决于所指向的对象,UROWID的大小会有所变化。
    以上列表中还少了许多类型,如INT、INTEGER、SMALLINT、FLOAT、REAL等。这些类型实际上都是在上表所列的某种类型的基础上实现的,它们只是固有Oracle类型的同义词。

    2 字符和二进制串类型

    Oracle中的字符数据类型包括CHAR、VARCHAR2以及带“N“的相应”变体“(NCHAR和NVARCHAR2),这些字符数据类型能存储2,000字节或4,000字节的文本。这些文本会由数据库根据需要在不同字符集之间转换。字符集(chrarcter set)是各个字符的一种二进制表示(用位和字节表示)。目前有多种不同的字符集,每种字符集能表示不同的字符,例如:
    US7ASCII字符集是128字符的ASCII标准表示。它使用字节的低7位表示这128个字符。
    WE8ISO8859P1字符集是一种西欧字符集,不仅能不是128个ASCII字符,还能表示128个扩展字符,这个字符集使用了字节的全部8位。

    2.1 NLS概述

    国家语言支持(National Language Support)。NLS是数据库的一个非常强大的特性,NLS控制着数据的许多方面。例如,它控制着数据如何存储;还有我们在数据中是会看到多个逗号和一个句号(如12.000,000.01),还是会看到多个点号和一个逗号(如12.000.000,01)。

    它控制着以下两个方面:
    文本数据持久存储在磁盘上时如何编码
    透明地将数据从一个字符集转换到另一个字符集

    假设你在数据库中用WE8ISO8859P1字符集存储8位的数据,但是你的某些客户使用的是一种7位字符集,如US7ASCII。这些客户不想要8位的数据,需要从数据库将数据转换为他们能用的形式。尽管听上去不错,但是如果你不知道会发生这种转换,就会发现,过一段时间后,数据会“丢失“字符,WE8ISO8859P1字符集中的某些字符在US7ASCII中并没有,这些字符会转换为US7ASCII中的某个字符。原因就在于这里发生了字符集转换。简而言之,如果你从数据库获取了使用字符集1的数据,将其转换为使用字符集2,再把这些数据插入回数据库中(完成以上的逆过程),就极有可能大幅修改数据。字符集转换过程通常会修改数据,而你往往会把一个较大的字符集(在此例中就是8位字符集)映射到一个较小的字符集(此例中的7位字符集)。这是一种有损转换(lossy conversion),字符就会被修改,这只是因为:较小的字符集不可能表示较大字符集中的每一个字符。但是这种转换必须发生。如果数据库以一种单字节字符集存储数据,但是客户(如一个Java应用,因为Java语言使用Unicode)希望数据采用多字节表示,就必须执行转换,只有这样客户应用才能使用这些数据。

    2.2 字符串

    Oracle中有4种基本的字符串类型,分别是CHAR、VARCHAR2、NCHAR和NVARCHAR2。在Oracle中,所有串都以同样的格式存储。在数据库块上,最前面都有一个1~3字节的长度字段,其后才是数据,如果数据为NULL,长度字段则表示一个但字节值0xFF。
    注意 Oracle中尾部的NULL列占用0字节存储空间,这说明,如果表中的“最后一列”为NULL,Oracle不会为之存储任何内容。如果最后两列都是NULL,那么对这两列都不会存储任何内容。但是,如果位于NULL列之后的某个列要求为not null(即不允许为null),Oracle会使用null标志来指示这个列缺少值。

    如果串的长度小于或等于250(0x01~0xFA),Oracle会使用1个字节来表示长度。对于所有长度超过250的串,都会在一个标志字节0xFE后跟有两个字节来表示长度。

    scott@ORCL>create table t
      2  ( char_column char(20),
      3     varchar2_column varchar2(20)
      4  )
      5  /
    
    表已创建。
    
    scott@ORCL>insert into t values ( 'Hello World', 'Hello World' );
    
    已创建 1 行。
    
    scott@ORCL>select * from t;
    
    CHAR_COLUMN          VARCHAR2_COLUMN
    -------------------- --------------------
    Hello World          Hello World
    
    scott@ORCL>select * from t where char_column = 'Hello World';
    
    CHAR_COLUMN          VARCHAR2_COLUMN
    -------------------- --------------------
    Hello World          Hello World
    
    scott@ORCL>select * from t where varchar2_column = 'Hello World';
    
    CHAR_COLUMN          VARCHAR2_COLUMN
    -------------------- --------------------
    Hello World          Hello World

    到目前为止,两个列看上去好像是一样的,但实际上这里发生了一些隐式转换,在与CHAR列比较时,CHAR(12)直接量('Hello World’)已经提升为一个CHAR(20),并在其中填充了空格。这种转换肯定已经发生了,因为Hello World 与没有尾部空格的Hello World并不相同。可以确认这两个串是截然不同的:

    scott@ORCL>select * from t where char_column = varchar2_column;
    
    未选定行

    它们彼此并不相等。我们要么必须用空格填充VARCHAR2_COLUMN列,使其长度到达20字节,要么必须从CHAR_COLUMN列截去尾部的空格,如下:

    scott@ORCL>select * from t where trim(char_column) = varchar2_column;
    
    CHAR_COLUMN          VARCHAR2_COLUMN
    -------------------- --------------------
    Hello World          Hello World
    
    scott@ORCL>select * from t where char_column = rpad( varchar2_column, 20 );
    
    CHAR_COLUMN          VARCHAR2_COLUMN
    -------------------- --------------------
    Hello World          Hello World
    

    对于使用变长串的应用,绑定输入时会出现问题,而且肯定会得到“没有找到数据“之类的错误:

    scott@ORCL>variable varchar2_bv varchar2(20)
    scott@ORCL>exec :varchar2_bv := 'Hello World';
    
    PL/SQL 过程已成功完成。
    
    scott@ORCL>select * from t where char_column = :varchar2_bv;
    
    未选定行
    
    scott@ORCL>select * from t where varchar2_column = :varchar2_bv;
    
    CHAR_COLUMN          VARCHAR2_COLUMN
    -------------------- --------------------
    Hello World          Hello World

    在此,搜索VARCHAR2串成功了,但是搜索CHAR列未成功。VARCHAR2绑定变量不会像字符串直接量那样提升为CHAR(20)。要完成绑定,解决方案是使用CHAR类型:

    scott@ORCL>variable char_bv char(20)
    scott@ORCL>exec :char_bv := 'Hello World';
    
    PL/SQL 过程已成功完成。
    
    scott@ORCL>select * from t where char_column = :char_bv;
    
    CHAR_COLUMN          VARCHAR2_COLUMN
    -------------------- --------------------
    Hello World          Hello World
    
    scott@ORCL>select * from t where varchar2_column = :char_bv;
    
    未选定行

    不过,如果混合使用并匹配VARCHAR2和CHAR,你就会不断地遭遇这个问题。不仅如此,开发人员现在还必须在应用中考虑字段宽度。如果开发人员喜欢使用RPAD()技巧将绑定变量转换为某种能与CHAR字段比较的类型(当然,与截断(TRIM)数据库列相比,填充绑定变量的做法更好一些,因为对列应用函数TRIM很容易导致无法使用该列上现有的索引),可能必须考虑到经过一段时间后列长度的变化。如果字段的大小有变化,应用就会受到影响,因为它必须修改字段宽度。

    正是由于以下这些原因:定宽的存储空间可能导致表和相关索引比平常大出许多还伴随着绑定变量问题,所以无论什么场合我都会避免使用CHAR类型。即使是CHAR(1)字段(即单字符字段)也不建议使用CHAR类型。

    1. 字符串语法

    VARCHAR2<SIZE><BYTE|CHAR>                 <SIZE>是介于1~4,000之间的一个数,表示最多占用4,000字节的存储空间。
    CHAR(<SIZE><BYTE|CHAR>)                        <SIZE>是介于1~2,000之间的一个数,表示最多占用2,000字节的存储空间
    NVARCHAR2(<SIZE>)                                    <SIZE>是一个大于0的数,其上界由国家字符集指定
    NCHAR(<SIZE>)                                             <SIZE>是一个大于0的数,其上界由国家字符集指定

    2. 字节或字符

    VARCHAR2和CHAR类型支持两种指定长度的方法:
    用字节指定:VARCHAR2(12 byte)。这能支持最多12字节的数据, 在一个多字节字符集中,这可能这是两个字符。
    用字符指定:VARCHAR2(12 char)。这将支持最多12字符的数据,可能是多达40字节的信息。

    使用UTF8之类的多字节字符集时,建议你在VARCHAR2/CHAR定义中使用CHAR修饰符,也就是说,使用VARCHAR2(80 CHAR),而不是VARCHAR2(80),因为你的本意很可能是定义一个实际上能存储80字符数据的列。

    下面这个小例子展示了BYTE和CHAR之间的区别,并显示出上界的作用。我们将创建一个包括3列的表,前两列的长度分别是1字节和1字符,最后一列是4,000字符。

    scott@ORCL>select *
      2  from nls_database_parameters
      3  where parameter = 'NLS_CHARACTERSET';
    
    PARAMETER            VALUE
    ----------------    ---------------------
    NLS_CHARACTERSET    AL32UTF8
    
    
    scott@ORCL>create table t
      2  ( a varchar2(1),
      3     b varchar2(1 char),
      4     c varchar2(4000 char)
      5  )
      6  /
    
    表已创建。

    现在,如果想在这个表中插入一个UTF字符,这个字符长度为2个字节,可以观察到以下结果:

    scott@ORCL>insert into t (a) values (unistr('\00d6'));
    insert into t (a) values (unistr('\00d6'))
                              *
    第 1 行出现错误:
    ORA-12899: 列 "SCOTT"."T"."A" 的值太大 (实际值: 2, 最大值: 1)

    这个例子展示了两点:
    1. VARCHAR2(1 byte)的单位是字节,而不是字符。这里确实只有一个Unicode字符,但是它在一个字节中放不下。
    2. 将应用从单字节定宽字符集移植到一个多字节字符集时,可能会发现原来在字段中能放下的文本现在却无法放下。

    第二点的原因是,在一个单字节字符集中,包含20个字符的字符串长度就是20字节,完全可以在一个VARCHAR2(20)中放下。不过,在一个多字节字符集中,20个字符的字符串长度可以到达80字节(如果每个字符用4个字节表示),这样一来,20个Unicode字符很可能无法在20个字节中放下。你可能会考虑将DDL修改为VARCHAR2(20 CHAR),或者在运行DDL创建表时使用前面提到的NLS_LENGTH_SEMANTICS会话参数。

    scott@ORCL>insert into t (b) values (unistr('\00d6'));
    
    已创建 1 行。
    
    scott@ORCL>select length(b), lengthb(b), dump(b) dump from t;
    
     LENGTH(B)  LENGTHB(B)  DUMP
    ----------  ----------  ----
             1          2   Typ=1 Len=2: 195,150
    

    这个INSERT成功了,而且可以看到,所插入数据的长度(LENGTH)就是一个字符,所有字符串函数都以字符为单位工作。这个字段的长度是一个字符,但是LENGTHB函数(字节长度)显示这个字段占用了2字节的存储空间,另外DUMP函数显示了这些字节到底是什么。这个例子展示了 VARCHAR2(N)并不一定存储N个字符,而只是存储N个字节

    人们经常遇到的另一个问题是:VARCHAR2的最大字节长度为4,000,而CHAR的最大字节长度为2,000。

    scott@ORCL>declare
      2     l_data varchar2(4000 char);
      3     l_ch varchar2(12 char) := unistr( '\00d6' );
      4     begin
      5             l_data := rpad( l_ch, 4000, l_ch );
      6             insert into t ( c ) values ( l_data );
      7     end;
      8  /
    declare
    *
    第 1 行出现错误:
    ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
    ORA-06512: 在 line 6
    

    在此显示出,一个4,000字符的字符串实际上长度为8,000字节,这样一个字符串无法永久地存储在一个VARCHAR2(4000 CHAR)字段中。这个字符串能放在PL/SQL变量中,因为在PL/SQL中VARCHAR2最大可以到达32KB。不过,存储在表中时,VARCHAR2则被硬性限制为最多只能存放4,000字节。我们可以成功地存储其中2,000个字符:

    scott@ORCL>declare
      2     l_data varchar2(4000 char);
      3     l_ch varchar2(12 char) := unistr( '\00d6' );
      4     begin
      5             l_data := rpad( l_ch, 2000, l_ch );
      6             insert into t ( c ) values ( l_data );
      7     end;
      8  /
    
    PL/SQL 过程已成功完成。
    
    scott@ORCL>select length( c ), lengthb( c )
      2  from t
      3  where c is not null;
    
     LENGTH(C) LENGTHB(C)
    ---------- ----------
          2000       4000

    如上图,它占用了4,000字节的存储空间。

    3. NVARCHAR2和NCHAR

    它们与相应的VARCHAR2和CHAR是一样的,只是有以下不同:
    文本采用数据库的国家字符集来存储和管理,而不是默认字符集。
    长度总是字符数,而CHAR/VARCHAR2可能会指定是字节还是字符。
    数据库的国家字符集有两个可取值:UTF8或AL16UTF16。这使得NCHAR和NVARCHAR类型很适于只存储多字节数据。

    3 二进制串:RAW类型

    Oracle除了支持文本,还支持二进制数据的存储。CHAR和VARCHAR2类 型需要进行字符集转换,而二进制数据不会做这种字符集转换。因此,二进制数据类型适于存储加密信息,加密数据不是“文本“, 而是原文本的一个二进制表示、包含二进制标记信息的字处理文档,等等。如果数据库不认为这些数据是”文本“,这些数据就应该采用一种二进制数据类型来存储,另外不应该应用字符集转换的数据也要使用二进制数据类型存储。

    Oracle支持3种数据类型来存储二进制数据:
    RAW类型,它很适合存储多达2,000字节的RAW数据。
    BLOB类型,它支持更大的二进制数据。
    LONG RAW类型,这是为支持向后兼容性提供的,新应用不应考虑使用这个类型。

    二进制RAW类型的语法很简单:

    RAW(<size>)

    例如,以下代码创建了一个每行能存储12字节二进制信息的表:

    scott@ORCL>create table t ( raw_data raw(16) );
    
    表已创建。

    从磁盘上的存储来看,RAW类型与VARCHAR2类型很相似。RAW类型是一个变长的二进制串,这说明前面创建的表T可以存储1~16字节的二进制数据。它不会像CHAR类型那样用空格填充。

    处理RAW数据时,它被隐式地转换为一个VARCHAR2类型,也就是说,诸如SQL*Plus之类的许多工具不会直接显示RAW数据,而是会将其转换为一种十六进制格式来显示。在以下例子中,我们使用SYS_GUID()在表中创建了一些二进制数据,SYS_GUID()是一个内置函数,将返回一个全局惟一的16字节RAW串(GUID就代表全局惟一标识符,globally unique identifier):

    scott@ORCL>insert into t values ( sys_guid() );
    
    已创建 1 行。
    
    scott@ORCL>select * from t;
    
    RAW_DATA
    --------------------------------
    A6A418FD9A6040A4B1DBB352CD5CBA9A
    

    首先,RAW数据看上去就像是一个字符串。SQL*Plus就是以字符串形式获取和打印RAW数据,但是RAW数据在磁盘上并不存储为字符串。SQL*Plus不能在屏幕上打印任意的二进制数据。要记住,二进制数据可能包含诸如回车或换行等控制字符,还可能是一个Ctrl+G字符,这会导致终端发出“嘟嘟“的叫声。
    其次,RAW数据看上去远远大于16字节,实际上,在这个例子中,你会看到32个字符。这是因为,每个二进制字节都显示为两个十六进制字符。所存储的RAW数据其实长度就是16字节,可以使用Oracle DUMP函数确认这一点。在此,我“转储“了这个二进制串的值,并使用了一个可选参数来指定显示各个字节值时应使用哪一种进制。这里使用了基数16,从而能将转储的结果与前面的串进行比较:

    scott@ORCL>select dump(raw_data,16) from t;
    
    DUMP(RAW_DATA,16)
    ----------------------------------------
    Typ=23 Len=16: a6,a4,18,fd,9a,60,40,a4,b1,db,b3,52,cd,5c,ba,9a

    DUMP显示出,这个二进制串实际上长度为16字节(LEN=16),另外还逐字节地显示了这个二进制数据。可以看到,这个转储显示与SQL*Plus将RAW数据获取为一个串时所执行的隐式转换是匹配的。另一个反向上(插入)也会执行隐式转换:

    scott@ORCL>insert into t values ( 'abcdef' );
    
    已创建 1 行。

    这不会插入串abcdef,而会插入一个3字节的RAW数据,其字节分别是AB、CD、EF,如果用十进制表示则为字节171、205、239。如果试图使用一个包含非法16进制字符的串,就会收到一个错误消息:

    scott@ORCL>select dump(raw_data,16) from t;
    
    DUMP(RAW_DATA,16)
    --------------------------------------------------------------------------------
    --------------------------------------------------------------------------------
    ----------------------------------------
    Typ=23 Len=16: a6,a4,18,fd,9a,60,40,a4,b1,db,b3,52,cd,5c,ba,9a
    Typ=23 Len=3: ab,cd,ef
    
    scott@ORCL>insert into t values ( 'abcdefgh' );
    insert into t values ( 'abcdefgh' )
                                 *
    第 1 行出现错误:
    ORA-01465: 无效的十六进制数字
    

    RAW类型可以加索引,还能在谓词中使用,它与其他任何数据类型有同样的功能。不过,必须当心避免不希望的隐式转换,而且必须知道确实会发生隐式转换。
    可以使用以下内置函数来执行这种操作:
    HEXTORAW:将十六进制字符串转换为RAW类型
    RAWTOHEX:将RAW串转换为十六进制串
    SQL*Plus将RAW类型获取为一个串时,会隐式地调用RAWTOHEX函数,而插入串时会隐式地调用HEXTORAW函数。应该避免隐式转换,而在编写代码时总是使用显示转换,这是一个很好的实践做法。所以前面的例子应该写作:

    scott@ORCL>select rawtohex(raw_data) from t;
    
    RAWTOHEX(RAW_DATA)
    ----------------------------------------------------------------
    A6A418FD9A6040A4B1DBB352CD5CBA9A
    ABCDEF
    
    scott@ORCL>insert into t values ( hextoraw('abcdef') );
    
    已创建 1 行。
    
    scott@ORCL>select rawtohex(raw_data) from t;
    
    RAWTOHEX(RAW_DATA)
    ----------------------------------------------------------------
    A6A418FD9A6040A4B1DBB352CD5CBA9A
    ABCDEF
    ABCDEF

     

    转载于:https://my.oschina.net/u/1862478/blog/1931520

    展开全文
  • 写了个Oracle转换函数,发现当数据为负数的时候,无法转换,因为业务前端入库的数据是32位,当JAVA进行有符号转换为INT类型的时候,会产生负数,而我要再次转换为二进制进行位的判断,网上找了好多,都不能做有符号...

    写了个Oracle转换函数,发现当数据为负数的时候,无法转换,因为业务前端入库的数据是32位,当JAVA进行有符号转换为INT类型的时候,会产生负数,而我要再次转换为二进制进行位的判断,网上找了好多,都不能做有符号数字的转换,因此按照负数的二进制表示法重新写了个函数:

    负数的二进制方法的表示方法:例如 -5

    第一步:首先要把5变成101的二进制形式

    第二步:再者就是安位取反,(形成前面全是1)010

    第三步:在最后加1 形成:11111111 11111111 11111111 11111011

    CREATE OR REPLACE FUNCTION NUMBER_2_BIT(V_NUM NUMBER) RETURN VARCHAR IS

    V_RTN VARCHAR(2000);

    V_N1  NUMBER;

    V_N2  NUMBER;

    BEGIN

    V_N1 := ABS(V_NUM);

    --如果为正数

    IF SIGN(V_NUM) > 0 THEN

    LOOP

    V_N2  := MOD(V_N1, 2);

    V_N1  := ABS(TRUNC(V_N1 / 2));

    V_RTN := TO_CHAR(V_N2) || V_RTN;

    EXIT WHEN V_N1 = 0;

    END LOOP;

    --dbms_output.put_line('正数结果'||V_RTN);

    --补全32位高位0

    SELECT lpad(V_RTN,32,0)

    INTO   V_RTN

    FROM dual;

    --dbms_output.put_line('正数补全结果'||V_RTN);

    ELSE

    --转换为二进制同时按位取反

    LOOP

    V_N2 := MOD(V_N1, 2);

    IF V_N2 = 1 THEN

    V_N2 := 0;

    ELSIF V_N2 = 0 THEN

    V_N2 := 1;

    END IF;

    V_N1  := ABS(TRUNC(V_N1 / 2));

    V_RTN := TO_CHAR(V_N2) || V_RTN;

    EXIT WHEN V_N1 = 0;

    END LOOP;

    --dbms_output.put_line('负数结果'||V_RTN);

    --补全32位高位1

    SELECT lpad(V_RTN,32,1)

    INTO   V_RTN

    FROM dual;

    --dbms_output.put_line('负数补全1结果'||V_RTN);

    --二进制转换为10机制,同时+1

    SELECT SUM(data1) + 1

    INTO V_N1

    FROM (SELECT substr(V_RTN, rownum, 1) * power(2, length(V_RTN) - rownum) data1

    FROM dual

    CONNECT BY rownum <= length(V_RTN));

    -- dbms_output.put_line('转换为十进制数结果'||V_RTN);

    ----转换为二进制

    LOOP

    V_N2 := MOD(V_N1, 2);

    V_N1  := ABS(TRUNC(V_N1 / 2));

    V_RTN := TO_CHAR(V_N2) || V_RTN;

    EXIT WHEN V_N1 = 0;

    END LOOP;

    --dbms_output.put_line('负数转换结果'||V_RTN);

    --补全32位高位0

    SELECT lpad(V_RTN,32,0)

    INTO   V_RTN

    FROM dual;

    --dbms_output.put_line('负数补全0结果'||V_RTN);

    END IF;

    RETURN V_RTN;

    END;

    展开全文
  • 写了个Oracle转换函数,发现当数据为...当JAVA进行有符号转换为INT类型的时候,会产生负数,而我要再次转换为二进制进行位的判断,网上找了好多,都不能做有符号数字的转换,因此按照负数的二进制表示法重新写了个...

    写了个Oracle转换函数,发现当数据为负数的时候,无法转换,因为业务前端入库的数据是32位,当JAVA进行有符号转换为INT类型的时候

    写了个Oracle转换函数,发现当数据为负数的时候,无法转换,,因为业务前端入库的数据是32位,当JAVA进行有符号转换为INT类型的时候,会产生负数,而我要再次转换为二进制进行位的判断,网上找了好多,都不能做有符号数字的转换,因此按照负数的二进制表示法重新写了个函数:

    负数的二进制方法的表示方法:例如 -5

    第一步:首先要把5变成101的二进制形式

    第二步:再者就是安位取反,(形成前面全是1)010

    第三步:在最后加1 形成:11111111 11111111 11111111 11111011

    CREATE OR REPLACE FUNCTION NUMBER_2_BIT(V_NUM NUMBER) RETURN VARCHAR IS

    V_RTN VARCHAR(2000);

    V_N1 NUMBER;

    V_N2 NUMBER;

    BEGIN

    V_N1 := ABS(V_NUM);

    --如果为正数

    IF SIGN(V_NUM) > 0 THEN

    LOOP

    V_N2 := MOD(V_N1, 2);

    V_N1 := ABS(TRUNC(V_N1 / 2));

    V_RTN := TO_CHAR(V_N2) || V_RTN;

    EXIT WHEN V_N1 = 0;

    END LOOP;

    --dbms_output.put_line('正数结果'||V_RTN);

    --补全32位高位0

    SELECT lpad(V_RTN,32,0)

    INTO V_RTN

    FROM dual;

    --dbms_output.put_line('正数补全结果'||V_RTN);

    ELSE

    --转换为二进制同时按位取反

    LOOP

    V_N2 := MOD(V_N1, 2);

    IF V_N2 = 1 THEN

    V_N2 := 0;

    ELSIF V_N2 = 0 THEN

    V_N2 := 1;

    END IF;

    V_N1 := ABS(TRUNC(V_N1 / 2));

    V_RTN := TO_CHAR(V_N2) || V_RTN;

    EXIT WHEN V_N1 = 0;

    END LOOP;

    --dbms_output.put_line('负数结果'||V_RTN);

    --补全32位高位1

    SELECT lpad(V_RTN,32,1)

    INTO V_RTN

    FROM dual;

    --dbms_output.put_line('负数补全1结果'||V_RTN);

    --二进制转换为10机制,同时+1

    SELECT SUM(data1) + 1

    INTO V_N1

    FROM (SELECT substr(V_RTN, rownum, 1) * power(2, length(V_RTN) - rownum) data1

    FROM dual

    CONNECT BY rownum <= length(V_RTN));

    -- dbms_output.put_line('转换为十进制数结果'||V_RTN);

    ----转换为二进制

    LOOP

    V_N2 := MOD(V_N1, 2);

    V_N1 := ABS(TRUNC(V_N1 / 2));

    V_RTN := TO_CHAR(V_N2) || V_RTN;

    EXIT WHEN V_N1 = 0;

    END LOOP;

    --dbms_output.put_line('负数转换结果'||V_RTN);

    --补全32位高位0

    SELECT lpad(V_RTN,32,0)

    INTO V_RTN

    FROM dual;

    --dbms_output.put_line('负数补全0结果'||V_RTN);

    END IF;

    RETURN V_RTN;

    END;

    logo.gif

    f68f2add0b68e4f9810432fce46917b7.png

    本文原创发布php中文网,转载请注明出处,感谢您的尊重!

    展开全文
  • 操作二进制数据

    2011-08-19 13:40:00
    SQL Server使用Binary类型表示二进制数据Oracle使用Blob(大二进制对象)类型表示。在JDBC中操作二进制对象和其他数据类型有所不同,二进制对象通常使用输入、输出流的方式来写入和读取。本节介...
  • <p>Which is pretty much exactly what Oracle suggests <a href="https://blogs.oracle.com/oswald/entry/php_s_mysqli_extension_storing" rel="nofollow noreferrer">right here</a>.</p> <p>But for some ...
  • Oracle中如何读取和写入二进制数据

    万次阅读 2006-10-12 17:54:00
    概要:从数据库中如何读取和写入二进制数据,是一个比较有趣的话题。众说周知,数据库中的文件类型数据,大多以二进制形式存储,这就意味着,我们可以把图片和其他文件转化为二进制代码写入数据库,读取的时候再把二...
  • ORACLE 10进制转换2进制

    千次阅读 2011-08-13 19:59:16
    之前写了个转换函数,发现当数据为负数的时候,无法转换,因为业务前端入库的数据是32位,当JAVA进行有符号转换为INT类型的时候,会产生负数,而我要再次转换为二进制进行位的判断,网上找了好多,都不能做有符号...
  • 上周接到一个需求,需要用到对Oracle数据库BLOB类型进行读写操作,BLOB里主要存图片文件。本来想找个DAO框架用用,但是感觉好久没用JDBC写了,就用了JDBC然而平时框架用久了不会遇到也不会注意的问题在JDBC上接连...
  • //测试存储二进制文件@Testpublic void test() throws IOException{InputStream in=new FileInputStream("E:\\test.txt");byte[] tblob=new byte[in.available()];in.read(tblob);in.close();Session ses =...
  • ),早期数据库因为要存储声音、图片、以及可执行程序等二进制数据对象所以给该类对象取名为Blob。 在Web领域,Blob被定义为包含只读数据的类文件对象。Blob中的数据不一定是js原生数据形式。常见的File接口就继承...
  • 2.数据类型数据类型主要分为四类:字符型、数值型、日期型和其他类型。字符型:CHAR(n)、NCHAAR(n),n固定长度。按照Unicode存放,CHAR长度最大值是2000,NCHAR长度最大值1000。VARCHAR2(n)、NVARCHAR2(n)是可变长度...
  • 地图数据存放在sqlserver 2008中,使用mapxtreme7 开发时,使用Feature.Update()方法时出错的提示包含“MSSQL 将截断字符串或二进制数据” 主要原因就是给某个字段赋值时,内容大于字段的长度或类型不符造成的 解决...
  • 本文以用一个在数据库中保存图片...首先我们要知道 Postgresql 中唯一一种二进制数据类型为 bytea, 表示字节数组或字节序列. 对应于Oracle和MySQL中的 blob. 下面是一个示例 defmodule Bytea.Model.Test do imp...
  • oracle数据库插入二进制文件

    千次阅读 2016-04-21 13:13:04
    1.创建表 大型对象(LOB)数据类型 ...最大4G,存储二进制数据。适用于存储图像、视频、音频等。 BFile 最大长度是4GB,在数据库外部保存的大型二进制对象文件,最大长度是4GB。这种外
  • 在偶然一次机会接触到这个问题,就找到了这个解决方法,收藏起来...Oracle数据库对应字段BLOB类型,实体对应字节数组类型(byte[]、@Type(type="org.springframework.orm.hibernate3.support.BlobByteArrayT...
  • Oracle中大文本数据类型Clob 长文本类型 (MySQL中不支持,使用的是text)Blob 二进制类型MySQL数据库Text 长文本类型TINYTEXT: 256 bytesTEXT: 65,535 bytes => ~64kbMEDIUMTEXT: 16,777,215 bytes => ~16...
  • MySQL 常见的数据类型有字符串类型、数字类型、时间类型、二进制类型。具体的分类如下图: 1. 字符串类型 字符串类型用于存储字符和字符串数据,主要包含三种具体的类型:定长字符串、变长字符串以及字符串大对象。...
  • Oracle 常用的数据类型

    2019-04-21 10:35:00
    (0) Oracle 数据类型 varchar2:可变长字符数据 char(size):定长字符数据 number(p,s):可变长数值数据 date:日期型数据 long:可变长字符数据,最大可达到2G clob:字符数据,最大可达到4G RAW(LONG RAW):原始的...
  • 前两天给朋友写的一段代码,特此总结在此。除Oracle以外的数据库应当都可以使用以下...二进制的字段是一个java.sql.Blob类型 private java.sql.Blob image; xdoclet要用的注释: @hibernate.property column...
  • Oracle 中有4 种基本的字符串类型,分别是CHAR、VARCHAR2、NCHAR 和NVARCHAR2。 在Oracle 中,所有串都以同样的格式存储。在数据库块上,最全面都有一个1~3 字节的长度字段,其后是数据。 1) CHAR():定长字符串...
  • 前两天给朋友写的一段代码,特此总结在此。除Oracle以外的数据库应当都...二进制的字段是一个java.sql.Blob类型private java.sql.Blob image;xdoclet要用的注释:@hibernate.propertycolumn="image"接下来就是保存文
  • oracle支持的数据类型

    2012-04-10 10:21:18
    RAW 固定长度的二进制数据 最大长度2000 bytes 可存放多媒体图象声音等 LONG RAW 可变长度的二进制数据 最大长度2G 同上 BLOB 二进制数据 最大长度4G CLOB 字符数据 最大长度4G NCLOB 根据字符集而定的字符数据 最大...
  • 数据库中提供了两种字段类型 Blob 和 Clob 用于存储大型字符串或二进制数据(如图片)。 Blob 采用单字节存储,适合保存二进制数据,如图片文件。 Clob 采用多字节存储,适合保存大型文本数据。 Oracle中处理BLOB...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,037
精华内容 414
关键字:

oracle二进制数据类型