您的位置:首页 > 数据库 > Oracle

Oracle12C--数据类型划分(二十七)

2017-05-09 09:50 197 查看
知识点的梳理:
Oracle中的varchar2与其他数据库的varchar完全一样;

使用UNICODE编码最大的方便之处是统一了字符与汉字的长度。这样在进行文字处理时会更加方便。但是,由于所有的字母都会按照十六进制保存,所以会存在浪费空间的问题
  

四类数据类型
标量类型(SCALAR,或称基本数据类型):用于保存单个值,例如字符串,数字,日期,布尔;
复合类型(COMPOSITE):复合类型可以在内部存放多种数值,类似于多个变量的集合,例如记录类型,嵌套表,索引表,可变数组等;
引用类型(REFERENCE):用于指向另一个不同对象,例如REF CURSOR,REF;
LOB类型:大数据类型,最多可以存储4GB的信息,主要用来处理二进制数据;

标量类型
标量类型也被称为基本数据类型

常见标量类型





数值型

NUMBER数据类型

采用十进制类型,需将十进制转为二进制进行计算
定义整型:NUMBER(n);
定义浮点型数据:NUMBER(m,n)

实例1:定义NUMBER变量

DECLARE

v_x NUMBER(3) ; --
最多只能为3位数字
v_y NUMBER(5,2) ; -- 3位整数,2位小数
BEGIN

v_x := -500 ;
v_y := 999.88 ;
DBMS_OUTPUT.put_line('v_x = ' || v_x) ;
DBMS_OUTPUT.put_line('v_y = ' || v_y) ;
DBMS_OUTPUT.put_line('加法运算:' || (v_x + v_y)) ; --
整数 +
浮点数 = 浮点数
END ;

/

效果:

v_x = -500

v_y = 999.88

加法运算:499.88

BINARY_INTEGER与PLS_INTEGER

说明:
两者具有相同的范围长度。与NUMBER比较,占用的范围更小;
采用二进制补码存储,运算性能比NUMBER高;

两者区别:
BINARY_INTEGER操作的数据大于其数据范围时,会自动转换为NUMBER型进行保存;
PLS_INTEGER操作的数据大于范围时,会抛出异常信息

示例1:验证PLS_INTEGER操作

DECLARE

v_pls1 PLS_INTEGER := 100 ;
v_pls2 PLS_INTEGER := 200 ;
v_result PLS_INTEGER ;
BEGIN

v_result := v_pls1 + v_pls2 ;
DBMS_OUTPUT.put_line('计算结果:' || v_result) ;
END ;

/

计算结果:300

BINARY_FLOAT与BINARY_DOUBLE
两者比NUMBER节约空间,同时范围更大,采用二进制存储数据;
示例1:验证BINARY_DOUBLE操作

DECLARE

v_float BINARY_FLOAT := 8909.51F ;
v_double BINARY_DOUBLE := 8909.51D ;
BEGIN

v_float := v_float + 1000.16 ;
v_double := v_double + 1000.16 ;
DBMS_OUTPUT.put_line('BINARY_FLOAT变量内容:' || v_float) ;
DBMS_OUTPUT.put_line('BINARY_DOUBLE变量内容:' || v_double) ;
END ;

/

计算结果:

BINARY_FLOAT变量内容:9.90966992E+003

BINARY_DOUBLE变量内容:9.9096700000000001E+003

两者定义的常量:这些常量只能在PL/SQL中使用。这些常量分别表示BINARY_FLOAT与BINARY_DOUBLE的数据范围,同时针对非数字与超过其类型最大值的数据标记





示例2:观察表示范围的常量内容

DECLARE

BEGIN

DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MIN_NORMAL = ' || BINARY_FLOAT_MIN_NORMAL) ;
DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MAX_NORMAL = ' || BINARY_FLOAT_MAX_NORMAL) ;
DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MIN_SUBNORMAL = ' || BINARY_FLOAT_MIN_SUBNORMAL) ;
DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MAX_SUBNORMAL = ' || BINARY_FLOAT_MAX_SUBNORMAL) ;
DBMS_OUTPUT.put_line('2、BINARY_DOUBLE_MIN_NORMAL = ' || BINARY_DOUBLE_MIN_NORMAL) ;
DBMS_OUTPUT.put_line('2、BINARY_DOUBLE_MAX_NORMAL = ' || BINARY_DOUBLE_MAX_NORMAL) ;
DBMS_OUTPUT.put_line('2、BINARY_DOUBLE_MIN_SUBNORMAL = ' || BINARY_DOUBLE_MIN_SUBNORMAL) ;
DBMS_OUTPUT.put_line('2、BINARY_DOUBLE_MAX_SUBNORMAL = ' || BINARY_DOUBLE_MAX_SUBNORMAL) ;
END ;

/

运行结果:

1、BINARY_FLOAT_MIN_NORMAL = 1.17549435E-038

1、BINARY_FLOAT_MAX_NORMAL = 3.40282347E+038

1、BINARY_FLOAT_MIN_SUBNORMAL = 1.40129846E-045

1、BINARY_FLOAT_MAX_SUBNORMAL = 1.17549421E-038

2、BINARY_DOUBLE_MIN_NORMAL = 2.2250738585072014E-308

2、BINARY_DOUBLE_MAX_NORMAL = 1.7976931348623157E+308

2、BINARY_DOUBLE_MIN_SUBNORMAL = 4.9406564584124654E-324

2、BINARY_DOUBLE_MAX_SUBNORMAL = 2.2250738585072009E-308

示例3:超过范围的计算

DECLARE

BEGIN

DBMS_OUTPUT.put_line('超过范围计算的结果:' ||

BINARY_DOUBLE_MAX_NORMAL * BINARY_DOUBLE_MAX_NORMAL) ;
DBMS_OUTPUT.put_line('超过范围计算的结果:' ||

BINARY_DOUBLE_MAX_NORMAL / 0) ;
END ;

/

运行结果:

超过范围计算的结果:Inf

超过范围计算的结果:Inf

字符型

CHAR与VARCHAR2

说明:
CHAR采用定长方式保存字符串。如果用户设置的内容不足其定义长度,则会自动补充空格;
VARCHAR2是可变字符串。如果设置的内容不足其长度,也不会为其补充内容;

示例1:观察CHAR和VARCHAR2的区别

DECLARE

v_info_char CHAR(10) ;
v_info_varchar VARCHAR2(10) ;
BEGIN

v_info_char := 'MLDN' ; --
长度不足10个
v_info_varchar := 'java' ; --
长度不足10个
DBMS_OUTPUT.put_line('v_info_char内容长度:' || LENGTH(v_info_char)) ;
DBMS_OUTPUT.put_line('v_info_varchar内容长度:' || LENGTH(v_info_varchar)) ;
END ;

/

运行结果:

v_info_char内容长度:10

v_info_varchar内容长度:4

NCHAR和NVARCHAR2
两者的特性与CHAR,VARCHAR2一样。区别在于它们保存的数据为UNICODE编码,中文与英文都会变为十六进制编码保存;
示例1:验证NCHAR和NVARCHAR2

DECLARE

v_info_nchar NCHAR(10) ;
v_info_nvarchar NVARCHAR2(10) ;
BEGIN

v_info_nchar := 'CSDN' ; --
长度不足10个
v_info_nvarchar := 'java高端培训' ; --
长度不足10个
DBMS_OUTPUT.put_line('v_info_nchar内容长度:' || LENGTH(v_info_nchar)) ;
DBMS_OUTPUT.put_line('v_info_nvarchar内容长度:' || LENGTH(v_info_nvarchar)) ;
END ;

/

运行结果:

v_info_nchar内容长度:10

v_info_nvarchar内容长度:8

LONG与LONG RAW
两者用于向后兼容;

LONG说明:
使用LONG的地方都会使用CLOB或NCLOB;
LONG用于存储字符流;
可以使用"UTL_RAW.cast_to_varchar2(RAW数据)"函数,将RAW转为字符串

LONG RAW说明:
使用LONG RAW的地方都替换为BLOB或BILE;
LONG RAW用于存储二进制数据流
为LONG RAW变量设置内容,要使用"UTL_RAW.cast_to_raw(字符串)"进行转换;

示例1:使用LONG和LONG RAW操作

DECLARE

v_info_long LONG ;
v_info_longraw LONG RAW ;
BEGIN

v_info_long := 'CSDN' ; --
直接设置字符串
v_info_longraw := UTL_RAW.cast_to_raw('JAVA高端培训') ; --
将字符串变为RAW
DBMS_OUTPUT.put_line('v_info_long内容:' || v_info_long) ;
DBMS_OUTPUT.put_line('v_info_longraw内容:' || UTL_RAW.cast_to_varchar2(v_info_longraw)) ;
END ;

/

运行结果:

v_info_long内容:CSDN

v_info_longraw内容:JAVA高端培训

ROWID与UROWID
ROWID表示的是一条数据的物理行地址,由18个字符组合而成,与ROWID伪列功能相同;
UROWID具备ROWID的功能,还增加了一个逻辑行地址,在PL/SQL中应将所有的ROWID交给UROWID管理;
示例1:使用ROWID及UROWID

DECLARE

v_emp_rowid ROWID ;
v_emp_urowid UROWID ;
BEGIN

SELECT ROWID INTO v_emp_rowid FROM emp WHERE empno=7369 ; --
取得ROWID
SELECT ROWID INTO v_emp_urowid FROM emp WHERE empno=7369 ; --
取得ROWID
DBMS_OUTPUT.put_line('7369雇员的ROWID = ' || v_emp_rowid) ;
DBMS_OUTPUT.put_line('7369雇员的UROWID = ' || v_emp_urowid) ;
END ;

/

运行结果:

7369雇员的ROWID = AAAX0rAAGAAAaRsAAA

7369雇员的UROWID = AAAX0rAAGAAAaRsAAA

日期型

DATE数据类型
用来存储日期时间数据;
可通过SYSDATE或SYSTIMESTAMP两个伪列来获取当前的日期时间;

主要字段索引:



示例1:定义DATE型变量

DECLARE

v_date1 DATE := SYSDATE ;
v_date2 DATE := SYSTIMESTAMP ;
v_date3 DATE := '19-9月-1981' ;
BEGIN

DBMS_OUTPUT.put_line('日期数据:' || TO_CHAR(v_date1,'yyyy-mm-dd hh24:mi:ss')) ;
DBMS_OUTPUT.put_line('日期数据:' || TO_CHAR(v_date2,'yyyy-mm-dd hh24:mi:ss')) ;
DBMS_OUTPUT.put_line('日期数据:' || TO_CHAR(v_date3,'yyyy-mm-dd hh24:mi:ss')) ;
END ;

/

运行结果:

日期数据:2017-02-15 16:33:47

日期数据:2017-02-15 16:33:47

日期数据:1981-09-19 00:00:00

TIMESTAMP数据类型

该类型与DATE的区别在于,可以提供更为准确的时间。但是要使用SYSTIMESTAMP伪列来为其赋值;
如果只是使用SYSDATE,那么TIMESTAMP与DATE没有任何区别;

示例1:定义TIMESTAMP型变量

DECLARE

v_timestamp1 TIMESTAMP := SYSDATE ;
v_timestamp2 TIMESTAMP := SYSTIMESTAMP ;
v_timestamp3 TIMESTAMP := '19-9月-1981' ;
BEGIN

DBMS_OUTPUT.put_line('日期数据:' || v_timestamp1) ;
DBMS_OUTPUT.put_line('日期数据:' || v_timestamp2) ;
DBMS_OUTPUT.put_line('日期数据:' || v_timestamp3) ;
END ;

/

运行结果:

日期数据:15-2月 -17 04.37.40.000000 下午

日期数据:15-2月 -17 04.37.40.372000 下午

日期数据:19-9月 -81 12.00.00.000000 上午

TIMESTAMP的两个扩充子类型:
TIMESTAMP WITH TIME ZONE:包含与格林威治时间的时区偏移量

DECLARE

v_timestamp TIMESTAMP WITH TIME ZONE := SYSTIMESTAMP ;
BEGIN

DBMS_OUTPUT.put_line(v_timestamp) ;
END ;

/

运行结果:
15-2月 -17 04.39.28.603000 下午 +08:00

TIMESTAMP WITH LOCAL TIME ZONE:不管是何种时区的数据,都使用当前数据库的时区;

DECLARE

v_timestamp TIMESTAMP WITH LOCAL TIME ZONE := SYSTIMESTAMP ;
BEGIN

DBMS_OUTPUT.put_line(v_timestamp) ;
END ;

/

运行结果:

15-2月 -17 04.40.43.309000 下午

INTERVAL数据类型

该类型可以保存两个时间戳之间的时间间隔,此类型分为两个子类型:

INTERVAL YEAR[(年的精度)] TO MONTHS:保存的和操作年与月之间的时间间隔,用户可以设置年的数据精度。默认值为2;
赋值格式:'年-月'

INTERVAL DAY[(天的精度)] TO SECEND[(秒的精度)]:保存和操作天,时,分,秒之间的时间间隔,默认为2。秒的默认值为6;
赋值格式:'天时:分:秒.毫秒'

当取得时间间隔后,可利用下列公式进行计算:



示例1:定义INTERVAL YEAR TO MONTHS类型变量

DECLARE

v_interval INTERVAL YEAR(3) TO MONTH := INTERVAL '27-09' YEAR TO MONTH ;
BEGIN

DBMS_OUTPUT.put_line('时间间隔:' || v_interval) ;
DBMS_OUTPUT.put_line('当前时间戳 +
时间间隔:' || (SYSTIMESTAMP + v_interval)) ;
DBMS_OUTPUT.put_line('当前日期 +
时间间隔:' || (SYSDATE + v_interval)) ;
END ;

/

运行结果:

时间间隔:+027-09

当前时间戳 + 时间间隔:15-11月-44 04.47.58.902000000 下午 +08:00

当前日期 + 时间间隔:15-11月-44

示例2:定义INTERVAL DAY TO SECOND类型变量

DECLARE

v_interval INTERVAL DAY(6) TO SECOND (3) := INTERVAL '8 18:19:27.367123909' DAY TO SECOND;
BEGIN

DBMS_OUTPUT.put_line('时间间隔:' || v_interval) ;
DBMS_OUTPUT.put_line('当前时间戳 +
时间间隔:' || (SYSTIMESTAMP + v_interval)) ;
DBMS_OUTPUT.put_line('当前日期 +
时间间隔:' || (SYSDATE + v_interval)) ;
END ;

/

运行结果:

时间间隔:+000008 18:19:27.367

当前时间戳 + 时间间隔:24-2月 -17 11.08.00.803000000 上午 +08:00

当前日期 + 时间间隔:24-2月 -17

布尔型
该类型保存TRUE,FALSE,NULL
示例1:定义布尔型变量

DECLARE

v_flag BOOLEAN ;
BEGIN

v_flag := true ;
IF v_flag THEN
DBMS_OUTPUT.put_line('条件满足。') ;
END IF ;
END ;

/

运行结果:
条件满足。

子类型
在某一标量类型的基础上定义更多约束,从而创建一个新的类型,这种新类型被称为子类型;
创建语法:

subtype 子类型名称 is
父数据类型[(约束)] [not null];

在定义子类型的时候必须设置好父数据类型。父类型可以是Oracle的各种数据类型

示例1:定义NUMBER子类型

DECLARE

SUBTYPE score_subtype IS NUMBER(5,2) NOT NULL ;
v_score score_subtype := 99.35 ;
--依据score_subtype类型为v_score变量赋值为99.35
BEGIN

DBMS_OUTPUT.put_line('成绩为:' || v_score) ;
END ;

/

运行结果:
成绩为:99.35

分析:定义了一个score_subtype的子类型,明确了精度。且不为NULL。该子类型定义完成后,实际上就相当于

定义了一个新类型,所以依然要依据此类型定义变量。但由于定义子类型时设置了不为NULL,所以在定义变量时要设置内容,

且不能超过要求精度;

示例2:定义VARCHAR2子类型

DECLARE

SUBTYPE string_subtype IS VARCHAR2(200) ;
v_company string_subtype ;--声明一个子类型为
string_subtype的变量v_company
BEGIN

v_company := 'csdn(www.csdn.cn)'
;
DBMS_OUTPUT.put_line(v_company) ;
END ;

/

运行结果:
csdn(www.csdn.cn)

分析:在声明子类型时,没有设置NOT NULL约束,所以在DECLARE中不用强制赋值

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Oracle