.NET程序员看Oracle数据类型

一、              数值类型:

1.         NUMBER:

Oracle里面其实只有一种数据类型,即NUMBER(好吧,我承认这句话有问题,但后面会说明)NUMBER可以指定精度(precision)和小数位数(scale),格式是NUMBER(p,s),其中p表示精度,s表示小数位数,两者都是可选的。

l         精度(precision),或总位数,表示最多可以存储几位数字。取值范围是1~38,默认是38

l         小数位数(scale),或小数点右边的位数,表示最多可以存储几位小数。取值范围是-84~127,而默认值取决于是否指定了精度:若没有指定精度,则小数位默认有最大的取值区间;若指定了精度而没有指定小数位数,则默认为0。如果插入的小数位数超过设定的位数,则Oracle会舍入到设定的位数。有人可能会问,小数位数怎么还能是负数呢?是的,其作用就是允许对小数点左边的值进行舍入,如类型是number(5,-2),则123就会被舍入为100

NUMBER类型有好几个变体,但它们本质上都是NUMBER类型。

l         INTEGER:映射到NUMBER(38),它不允许存储小数。

l         INTSMALLINT:完全映射到INTEGER

l         NUMERIC(p,s)DECIMAL(p,s)、或DEC(p,s):完全映射到NUMBER(p,s)。如果p未指定,则默认为38,即INTEGER

l         FLOAT(b):这里的b指定的也是“精度”,取值范围是1~126,默认值为126。但是它与p不同,这里使用的是二进制的精度。可以换算bpb*0.30103=p

l         REAL:映射到FLOAT(63)

l         DOUBLE PRECISION:映射到FLOAT

OracleNUMBER类型,比.NET所能支持的数值范围要大的多。设计数据库表时,可以根据存储的数值范围和精度的需要,来合理的选择ps。简单的对应,如果要存储整数(Byte/SByte/Int16/UInt16/Int32/UInt32/Int64/UInt64结构),使用INTEGER;如果要存储浮点数(Single/Double结构),使用FLOAT;如果要存储小数(Decimal结构),则使用NUMBER

 

2.         BINARY_FLOATBINARY_DOUBLE

Oracle 10g开始,引入了两种新的数值类型:BINARY_FLOATBINARY_DOUBLE。它们就是IEEE 754定义的单精度浮点数和双精度浮点数。这里修正了前面“Oracle里面其实只有一种数据类型,即NUMBER”的说法。

由于.NET里面的Single/Double结构,同样符合IEEE 754定义,因此它们和BINARY_FLOAT/BINARY_DOUBLE是完全对应的。

与之相反的是,NUMBER类型是使用十进制指数方式存储的,同时它是一种“软件数据类型”,即是在Oracle软件本身中实现的,因此性能要相对低一些。如果需要存储完全符合IEEE 754的浮点数,或者比较在意性能问题,则可以考虑选择BINARY_FLOATBINARY_DOUBLE类型。

 

二、              字符类型:

1.         CHAR/VARCHAR2及它们的变体NCHAR/NVARCHAR2

Oracle中有四种字符类型,可以按照定长/变长,和存储字符集两个维度的分类,将它们划分如下:

 

默认字符集

(NLS_CHARACTERSET)

国家字符集

(NLS_NCHAR_CHARACTERSET)

定长字符类型

CHAR

NCHAR

变长字符类型

VARCHAR2

NVARCHAR2

CHAR/NCHAR最多能存储2000个字节的字符串,VARCHAR2/NVARCHAR2最多能存储4000个字节的字符串。

一般情况下,不需要考虑定长字符类型。因为定长字符类型总是会用空格填充得到的串,使之达到一个固定宽度,所以它们实际浪费了存储空间。另一方面,这也会在字符串比较方面碰到麻烦。所以即使只是为了存储一个字符(Char结构),也没有必要使用定长字符类型。

CHARVARCHAR2,可以使用两种方式指定长度:

l         用字节数指定:VARCHAR2(10 byte)VARCHAR2(10),表示最多可以存储10个字节长度的字符串。这最多能存储几个字符,取决于数据库的默认字符集。在一个多字节字符集中,一个字符可能需要采用4个字节表示,那么最多就只能存储2个字符。

l         用字符数指定:VARCHAR2(10 char),这表示最多可以存储10个字符长度的字符串。

Oralce9i开始,数据库的国家字符集只能允许两种可能的取值:UTF8AL16UTF169i中是UTF1610g中是AL16UTF16)。所以NCHAR/NVARCHAR2就非常适合用来存储Unicode字符串。与CHAR/VARCHA2不同,指定NCHAR/NVARCHAR2的长度时,所使用的单位是字符:NVARCHAR2(10)就表示最多能存储10个字符长度的字符串。

.NET中,字符串(System)的编码固定是Unicode(确切的说是UTF-16),所以看起来它最适合对应的Oracle数据类型是NVARCHAR2。但是在一般的应用中,大部分的字符串应该是本土化的,所以完全可以对应VARCHAR2数据类型,当然前提是为数据库设置了合适的默认字符集。

 

2.         CLOBNCLOB

VARCHAR2/ NVARCHAR2类型的长度有限,当需要存储的字符串长度超过4000个字节时,就需要考虑使用大文本对象。

VARCHAR2/NVARCHAR2类似,CLOB/NCLOB也分别使用默认字符集和国家字符集编码进行存储。所不同的是,CLOB/NCLOB最多允许存储4GB的字符串。

CLOBNCLOB,以及后面提到的BLOB,在Oracle中成为“大对象”(Large Object),在存储和处理方面有一些特殊性。不过由于这篇文章的主题是讨论数据类型的选择,因此并不准备讨论这些话题。

 

三、              日期类型:

1.         DATE类型:

Oracle中的DATE类型表示日期和时间,它总是包含年、月、日、小时、分钟和秒。

.NET中的DateTime结构可以存储到DATE类型中。但DATE类型存在的明显的两个问题:(1)不支持小数秒;(2)不支持时区。

 

2.         TIMESTAMP类型:

Oracle 9i开始,引入了TIMESTAMP类型。TIMESTAMP类型与DATE类型非常类似,只不过另外还支持小数秒和时区。根据表示时区的不同形式,有三种具体的TIMESTAMP类型:TIMESTAMPTIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONE

基本的TIMESTAMP 数据类型的语法很简单:TIMESTAMP(n),这里n是可选的,用于指定秒的小数位数,取值范围是0~9,默认值为6。如果n取值为0,则功能上就等同于DATE类型。

TIMESTAMP WITH TIME ZONE 类型继承了TIMESTAMP 类型的所有特点,并增加了时区支持。存储数据时,TIMESTAMP WITH TIME ZONE 会在数据中存储指定的时区,时区成为数据本身的一部分。

TIMESTAMP WITH LOCAL TIME ZONE类型也支持时区。在存储数据时,Oracle会将时间转换为数据库所在时区的时间,而并不存储时区信息。读取时,Oracle认为这里存储的时间就是数据库所在时区的时间。

.NET 2.0 SP1开始,引入了一个新的DateTimeOffset结构,该结构包括一个 DateTime 值以及一个 Offset 属性,后者用于确定当前 DateTimeOffset 实例的日期和时间与协调世界时 (UTC) 之间的差值。我不知道它对于时区的处理是否与TIMESTAMP WITH TIME ZONE完全一致,但是直觉上它们应该是一个合适地映射。

另外,如果应用不需要记住源时区,只需要一种能对日期/时间类型提供一致的全球性处理数据类型,那么TIMESTAMP WITH LOCAL TIME ZONE已经提供了足够的支持。在对这个类型进行读取的时候,你需要确保对于会话设置了正确的时区。

 

3.         INTERVAL类型:

INTERVAL类型示一段时间或一个时间间隔。有两种INTERVAL类型:

INTERVAL YEAR TO MONTH表示几年加几个月,由于它并不常用,我打算根本不介绍它。

INTERVAL DAY TO SECOND表示几天几小时几分钟又几秒。实际上,它和.NET中的TimeSpan结构是对应的。它的语法是INTERVAL DAY(n) TO SECOND(m)。在此n 是一个可选的位数,支持天数分量,取值范围为09,默认为2m是秒字段小数部分中保留的位数,取值范围为09,默认为6

 

四、              二进制类型:

二进制类型用于存储二进制字节串,对应的.NET类型是Byte数组。

和字符类型类似,RAW类型用于存储不操作2000个字节的二进制数据,其中可以指定最多存储的字节数;而BLOB可用于存储最多4GB的二进制数据。

 

五、              布尔类型:

Oracle中没有布尔类型。如果需要存储.NET中的Boolean结构,可以存储”Y”/”N”或者”T”/”F”的单个字符(使用VARCHAR2(1)类型),或者存储1/0的单个数值(使用NUMBER(1)类型)

 

六、              其他类型:

1.         枚举类型:

Oracle中也没有枚举类型。和布尔类型相似,我们同样可以存储枚举常量的名称(使用VARCHAR2NVARCHAR2类型),或者存储枚举的基础类型(UnderlyingType)的值(使用NUMBER类型)

 

2.         可序列化的类型:

我们可以将可序列化类型的对象序列化保存到BLOB类型中,读取时则进行反序列化。

 

3.         Guid

Oracle不支持GUID类型,但是我们可以把Guid对象ToString()返回的字符串保存到数据库中。

 

 

最后总结如下:

类型分类

.NET类型

Oracle类型

数值类型

Byte

SByte

NUMBER(3)

 

Int16

UInt16

NUMBER(5)

 

Int32

UInt32

NUMBER(10)

 

Int64

UInt64

NUMBER(20)

 

Single

FLOAT(24)

 

Single

BINARY_FLOATIEEE 754

 

Double

DOUBLE PRECISION

 

Double

BINARY_DOUBLEIEEE 754

 

Decimal

NUMBER

字符类型

Char

VARCHAR2(1 Char)(本地字符集)

NVARCHAR2(1)Unicode字符集)

 

String(不超过4000个字节)

VARCHAR2(n Char)(本地字符集)

NVARCHAR2(n)Unicode字符集)

 

String

CLOB(本地字符集)

NCLOBUnicode字符集)

日期类型

DateTime

DATE(没有秒的小数位)

TIMESTAMP(不关心时区)

TIMESTAMP WITH LOCAL TIME ZONE(使用本地时区)

 

DateTimeOffset

TIMESTAMP WITH TIME ZONE

 

TimeSpan

INTERVAL DAY TO SECOND

二进制类型

Byte[](不超过2000个字节)

RAW(n)

 

Byte[]

BLOB

布尔类型

Boolean

VARCHAR2(1)(存储”Y”/”N””T”/”F”

 

Boolean

NUMBER(1)(存储1/0

枚举类型

枚举类型

VARCHAR2(n char)NVARCHAR2(n)(存储常量名称)

 

枚举类型

NUMBER(n)(存储基础类型的值)

可序列化类型

可序列化类型

BLOB(存储序列化二进制串)

Guid Guid VARCHAR2(38)(存储ToString()方法返回值)

 


posted on 2009-06-06 22:17  qmxle  阅读(2724)  评论(3编辑  收藏  举报

导航