oracle 数据库字符窜详细解释

来源:互联网 发布:mac os 10.12.1升级包 编辑:程序博客网 时间:2024/06/09 06:09
 
 

整理一下对于char,character,varchar,varchar2,nchar,nvarchar2,long,long raw及LOB类型之间比较

一、类型概念

char:
      定长的字符串类型,当存放的数据没有达到设定的最大限度时,会以空格补齐(测试方法及结果详见后面的"四.类型测试",以下同)。


character:
      经过测试与char基本相同,由于我个人的测试中没有找到不同的地方,所以怀疑char是character的缩写形式的同义词。

varchar:
      标准SQL中的可变长字符串类型,在标准SQL中允许存放空的字符串,但是在oracle中对其做出了一些改动,即:如果存放的是空字符串,则将其判断为null。另外被oracle保留在以后可能会对其做出改变。

varchar2:
      目前为止与varchar相同,可变长的字符串类型,但oracle官方承诺varchar在将来可能会被改变,但varchar2肯定不会改变,因此推荐使用varchar2。

nchar:
      与char一样是定长的字符串类型,会以空格补齐剩下的空间。专为UNICODE字符而设计的数据类型,用来存储NLS(National Language Support)数据,由于以单字节存放字符的类型只能使用于站用字节少的简单的语言,比如英文(26个字母),而中文,韩文等通常都需要2个甚至更多的字节,所以为了适应这种需要,制定了以N为开头的数据类型(UNICODE通常被用N来表示),这种类型一个字符需要占用2个字节的空间,简单字符(比如a)剩余的部分会用0补齐。

nvarchar2:
      与char和nchar的关系一样,是varchar2类型的UNICODE字符专用版。

long:
      大字段类型之一,此类型中存放的是可变长的字符串,专门用于存放超过4000字节的超长字符串,最大上限为2GB。但是,这个类型是被oracle保留下来并且将来会被取消掉的数据类型,替代它的是同为大字段类型的LOB(Large Object)类型。

long raw:
      与long互补,long raw可以存储非结构化数据,比如二进制文件,图形文件,或其他外部文件,最大上限2GB。虽然还没有混到像long那样将被抛弃的程度,但是,long raw能做到的LOB也一样能做到,Oracle公司建议在以后的程序中尽量使用LOB类型。

LOB:
      LOB(Large Object) 数据类型即能存储结构化数据外,也能存储非结构化数据,最大长度为4GB,比long和long raw更加灵活,Oracle公司建议,对大对象的操作尽量使用LOB

二、类型比较:

varchar与varchar2:

Oracle官方文档的解释:
Currently, VARCHAR is synonymous with VARCHAR2. However, in future releases of PL/SQL, to accommodate emerging SQL standards, VARCHAR might become a separate datatype with different comparison semantics. So, it is a good idea to use VARCHAR2 rather than VARCHAR

翻译:
目前, VARCHAR是VARCHAR2的同义词。然而,在未来的PL/SQL版本中,VARCHAR可能成为一个单独的数据类型与不同的比较语义,以适应新出现的SQL标准。 因此,使用VARCHAR2而不是VARCHAR是一个好习惯。

附加解释:二者的最大长度都为4000字节,详见下面的“三、类型长度解释”。

结论:varchar类型的语义在将来可能会变,而官方同样承诺varchar2的语义肯定不会变,所以推荐使用后者。


char与varchar2:

char是定长的,而varchar2是可变长的,通过测试可知对同样上限为20的char与varchar2类型的数据插入一个字符为a,那么前者的长度是20而后者的长度为1,这是因为char类型的a不满20字符的限制,因而自动在后面补上了19个空格,测试方法详见下面的“四、类型测试”。

两者的选择:
char是用空间换时间,而varchar2是用时间换空间,char类型虽然一定会填满设定的空间,但由于长度和顺序规则所以速度会比较快,varchar2则是以降低速度为代价节省空间。如果varchar2类型的数据会频繁被修改,则会出现行迁移的现象,降低数据库的速度,在这种时候应该使用char。关于“行迁移”详见下面的“五,行迁移与行链接”。


char与nchar:

两者都是定长,即用空格补齐剩余长度。主要区别在于char中一个简单字符(如:a)占一个字节,存放GBK编码的汉字存放2个字节,存放UTF-8编码的汉字占用3个字节,而nchar中根据所选字符集来定义存放字符的占用字节数,一般都为2个字节存放一个字符(无论是简单字符或是汉字),后者专门针对如:中文,韩文这样的字符,2者长度都为2000字节,顺便一提:假如定义char(20),括号中的不是字节数而是字符数,所以定义nchar的最大上限是nchar(1000)


varchar2与nvarchar2:
两者的关系与char和nchar的关系一样,只不过这2个都是可变长,最大长度为4000字节。


char,character,varchar,varchar2,nchar,nvarchar2的共同特点:
当插入空字符串时,则都会被转变为null(确切的说是没数据,因为null的实际解释是“不确定的数据”),但是要记住,空字符串和null是不一样的哦,如下图



long:
LONG 数据类型是一个遗留下来的而且在将来不会被支持的数据类型。它将被LOB(Large Object)数据类型所代替。特点如下:

      1、LONG 数据类型中存储的是可变长字符串,最大长度限制是2GB。
   2、曾经对于超出一定长度的文本,基本只能用LONG类型来存储,数据字典中很多对象的定义就是用LONG来存储的。
   3、LONG类型主要用于不需要作字符串搜索的长串数据,如果要进行字符搜索就要用varchar2类型。
   4、很多工具,包括SQL*Plus,处理LONG 数据类型都是很困难的。
   5、LONG 数据类型的使用中,要受限于磁盘的大小。
  能够操作 LONG 的 SQL 语句:
   1、Select语句
   2、Update语句中的SET语句
   3、Insert语句中的VALUES语句
   限制:
   1、一个表中只能包含一个 LONG 类型的列。
   2、不能索引LONG类型列。
   3、不能将含有LONG类型列的表作聚簇。
   4、不能在SQL*Plus中将LONG类型列的数值插入到另一个表格中,如insert into ...select。
   5、不能在SQL*Plus中通过查询其他表的方式来创建LONG类型列,如create table as select。
   6、不能对LONG类型列加约束条件(NULL、NOT NULL、DEFAULT除外),如:关键字列(PRIMARY KEY)不能是 LONG 数据类型。
   7、LONG类型列不能用在Select的以下子句中:where、group by、order by,以及带有distinct的select语句中。
   8、LONG类型列不能用于分布查询。


LOB:
Large Object的简写,是专门用于处理大对象的数据类型,一个表中可以有多个LOB字段,每个字段可以存储达4GB的数据,LOB主要分为以下两类:
      1、BLOB(Binary Large Object):适合于存放程序、图片、影音等非结构化文件。
      2、CLOB(Character Large Object):适用于存储文本型数据,例如文章、新闻、记录、日志等。


三、类型长度解释
      1、CHAR在表中字段的最大长度为2000字节(或字符),
      2、VARCHAR和VARCHAR2在表中字段的最大长度为4000字节(或字符),
      3、NCHAR在表中字段的最大长度为2000字节,根据所选字符集来定义存放字符的占用字节数,一般都为2个字节存放一个字符(不管字符或者汉字),所以在定义的时候为1000个字符长度,如:a NCHAR2(1000).注:括号中为字符数而不是字节。
      4、NVARCHAR2在表中字段最大长度为4000字节,同NCHAR一样,一般为2个字节存放一个字符或汉字。定义的时候最大长度为2000个字符,如:a NVARCHAR2(2000)
      5、CHARACTER类型最大长度为2000字节(或字符),经测试应与CHAR差不多,没有找到区别,怀疑CHAR为CHARACTER的缩写形式的同义词

      以上类型在变量定义中的最大长度均为32767(例如存储过程中定义变量),如下图:



四、类型测试
      首先,提供一个测量数据长度的函数DUMP(),此函数的输出格式如下:
类型 <[长度]>,符号/指数位 [数字1,数字2,数字3,......,数字20]
      我们借用此函数来确定上述几种字符串类型的长度和区别,另外大对象操作的数据类型(比如:long)无法使用DUMP()函数。以下的说明流程,请参照图“字符数据比较1”,而执行结果参照图“字符数据比较2”。
      1、建立张测试表名为typetest,在其中设定5种类型的数据分别为,char(20),varchar(20),varchar2(20),nchar(20),nvarchar2(20).注:character类型已经用同样的方法测试过,结果char相同
      

      2、在5个字段中都插入字符'a',
    

      3、用DUMP函数查询出结果,
如下图:




      4、如上图结果显示char和nchar的类型代码(Typ)为96,其他3个代码为1,char的长度(Len)为20,说明'a'占住第一个字节,省下19个字节则用空格补齐。nchar也是用空格补齐剩下的字节,之所以长度是40,是因为在建表的时候nchar(20)括号中的20是指20个字符,在nchar非特殊情况下每个字符都占了2字节,所以上限为40字节。varchar与varchar2的结果完全一样,说明2种类型现在还没有什么区别,并且长度为1,说明只有'a'所占的一个字节的空间。nvarchar2则同varchar2一样为可变长,并且由于也是一个字符占2字节,所以a所占的长度为'2'
      

      5、类型代码是oracle中对每种类型定义的ID名,类型代码可以在oracle文档中找到,下图"oracle常用数据类型代码"中列出了几种常见的类型代码。冒号后面的部分叫"符号/指数位",这个是说在数据库中该值的ASC码(例如:你看到的97就是a的ASC码,0是空字符,空格是32.我给出的图片省掉了后面很长的一部分,各位可以自己回去看看)


五、行迁移与行链接

      当一行的数据过长而不能插入一个单个数据块中时,可能发生两种事情:行链接(row chaining)或行迁移(row migration)。


      1、行链接:
      当第一次插入行时,由于行太长而不能容纳在一个数据块中时,就会发生行链接。在这种情况下,oracle会使用与该块链接的一块或多块数据块来容纳该行的数据。行连接经常在插入比较大的行时才会发生,如包含long, long row, lob等类型的数据。在这些情况下行链接是不可避免的。

      2、行迁移
      当修改不是行链接的行时,当修改后的行长度大于修改前的行长度,并且该数据块中的空闲空间已经比较小而不能完全容纳该行的数据时,就会发生行迁移。在这种情况下,Oracle会将整行的数据迁移到一个新的数据块上,而将该行原先的空间只放一个指针,指向该行的新的位置,并且该行原先空间的剩余空间不再被数据库使用,这些剩余的空间我们将其称之为空洞,这就是产生表碎片的主要原因,表碎片基本上也是不可避免的,但是我们可以将其降到一个我们可以接受的程度。

注意,即使发生了行迁移,发生了行迁移的行的rowid 还是不会变化,这也是行迁移会引起数据库I/O性能降低的原因。其实行迁移是行链接的一种特殊形式,但是它的起因与行为跟行链接有很大不同,所以一般把它从行链接中独立出来,单独进行处理。

原创粉丝点击