3.4 转换函数

  和Java语言类似,既然SQL语言中有数据类型,那么就会存在数据类型转换。

  在某些情况下,Oracle数据库需要使用某种数据类型的数据,而实际提供的却是另外一种数据类型,如果Oracle能自动将提供的数据类型数据转换为期望的数据类型的数据,这就是隐式数据类型转换。

  在Oracle中,对于直接赋值,Oracle数据库能够自动将VARCHAR2或CHAR转换到NUMBER和DATE类型,也可以将NUMBER和DATE自动转换到VARCHAR2类型。

  隐式数据类型转换,不只可以在上面提到的数据类型之间进行,在另一些数据类型之间也可以进行隐式转换,比如VARCHAR2可以被隐式地转换成ROWID。

  除了隐式数据类型转换,另外一种就是使用转换函数,显式地将某种数据类型转换成另外一种数据类型,也就是本节的重点。

  SQL语言提供了三种函数,实现从一种数据类型数据转换到另一种类型,它们分别是TO_CHAR、TO_NUMBER和TO_DATE。

3.4.1 对日期使用TO_CHAR函数

  之前,所有 Oracle 日期值默认都以 DD-MON-RR 格式显示,现在用TO_CHAR函数,将日期从默认格式转换为指定的格式,其语法形式如下:

  1. TO_CHAR(date[, 'fmt'])

  在使用该方法时,需要注意:格式模板必须放在单引号中,并且是大小写敏感的,格式模板可以包括任意日期格式元素。先来看一个例子,直接认识一下如何对日期使用TO_CHAR函数,其SQL语句如下:

  1. SELECT TO_CHAR(SYSDATE,'YYYY/MM/DD,HH24-MI-SS') FROM dual

  执行该SQL语句,结果为2013/06/17,15-44-06。在这个例子中,’YYYY/MM/DD,HH24- MI-SS’ 即格式模板,格式模板中的YYYY、MI这些称为格式元素。下面列举了日期格式的部分常用元素,如表3.8所示,其中“结果”一列是针对值为2013/06/17,15-44-06的日期类型按相应格式元素输出的结果。

表3.8 日期格式元素

格式元素 说 明 结 果
CC 世纪 21
YYYY 2013
YYY、YY、Y 年的最后三、二、一个数字 013、13、3
Y,YYY 年,在指定位置带逗号 2,013

续表

格式元素 说 明 结 果
YEAR 拼写年 TWENTY THIRTEEN
BC、AD 根据日期自动设置为BC、AD AD
B.C.、A.D. 根据日期自动设置为B.C.、A.D. A.D.
Q 季度 2
MM 月:两位数字值 06
MONTH 月份的全拼,右端补齐空格,总长为九个字符 JUNE
Mon 月份的前三个字母,首字母大写 Jun
RM 罗马数字月 VI
WW、W 在本年或本月的第几周 24、3
DAY 周几的全拼,右端补齐空格,总长为九个字符 MONDAY
DY 周几,前三个字母缩写 MON
DDD或DD或D 在本年、本月或本周的第几天 168、17、2(周日为第一天)

  接下来看看fm、th和sp这三个元素的使用。

  fm元素的作用就是用来删除填补的空或者前导0,对下面两个例子进行比较,就能很快明白。

  1. SELECT TO_CHAR(SYSDATE,'YYYY/MM/DD,HH24-MI-SS') FROM dual

  执行该SQL语句,结果为2013/06/17,15-44-06。

  1. SELECT TO_CHAR(SYSDATE,'fmYYYY/MM/DD,HH24-MI-SS') FROM dual

  执行该SQL语句,结果为2013/6/17,15-44-6。

  th和sp元素的作用是指定后缀来影响数字的显示,th加在数字后面表示序数,sp加在数字后面让数字以英文的形式显示,两个元素也可以结合起来使用。

  接下来列举时间格式的部分常用元素,如表3.9所示,其中“结果”一列是针对值为2013/06/17,15-44-06的日期类型按相应格式元素输出的结果。

表3.9 时间格式元素

格式元素 说 明 结 果
AM、PM 根据时间自动设置为 AM 或 PM PM
A.M.或P.M. 根据时间自动设置为 A.M. 或 P.M. P.M.
HH、HH12、HH24 12小时格式(1~12)、12小时格式(1~12)、24小时格式(0~23) 03、03、15
MI 分钟(0~59) 44
SS 秒(0~59) 06
SSSSS 从午夜12点以来经过的秒数 56656

  为了达到更好的输出效果,可以在格式模板中直接使用标点符号,作为各元素之间的间隔。还可以在格式模板中增加字符串,增加时需要用双引号括起来。

  假设现在需要显示雇员表中的雇员名字和雇佣日期,且雇佣日期以“Seventh of 6月 2013 15:44:6”格式显示,仅查询部门编号为60的雇员信息,其SQL语句如下:

  1. SELECT first_name, TO_CHAR(hire_date, 'fmDdspth "of" Mon YYYY fmHH24:MI:SS') AS "雇佣日期"
  2. FROM employees
  3. WHERE department_id = 60

  该SQL语句中还同时演示了sp和th元素的使用,执行SQL语句,显示结果如图3.7所示。

3.4 转换函数 - 图1


图3.7 对日期使用TO_CHAR函数

3.4.2 对数字使用TO_CHAR函数

  当数字与字符串混用且输出是字符串时,应该使用TO_CHAR函数将数字转换为需要的字符串(VARCHAR2),其语法形式如下:

  1. TO_CHAR(number[, 'fmt'])

  表3.10列举了将数字转换为字符时,一些常用的格式元素,其中“结果”一列是针对“输入”类的数据,按格式元素输出的结果。

表3.10 数字转换为字符格式元素

格式元素 说 明 输 入 举 例 结 果
9 数字宽度(9的个数决定显示宽度) 2468 999999 2468(前面有两个空格)
0 显示前导0 099999 002468
$ 美元符号 $999999 $2468(前面有两个空格)
L 本地货币符号 L9999 ¥2468
. 指定小数点位置 999999.99 2468.00(前面有两个空格)
, 指定逗号位置 999,999 2,468(前面有两个空格)
MI 将负数右边显示负号 -2468 999999MI 2468-(前面有两个空格)
PR 将负数加上括号 9999PR <2468>
EEEE 科学计数法 99.99999EEEE -2.46800E+03(前面无空格)
V 乘n个10,n由V后 9 的个数决定 999999V99 -246800(前面有两个空格)

  假设需要显示雇员表中的雇员名字和薪水,且薪水以“$17,000.00”格式显示,仅查询部门编号为90的雇员信息,其SQL语句如下:

  1. SELECT first_name AS "姓名", TO_CHAR(salary, '$99,999.99') AS "薪水"
  2. FROM employees
  3. WHERE department_id = 90

  执行SQL语句,显示结果如图3.8所示。

3.4 转换函数 - 图2


图3.8 对数字使用TO_CHAR函数

3.4.3 TO_NUMBER函数

  在使用SQL语言的数据类型转换过程中,不可能总是向字符类型转换,有时也需要将字符串转换成数字,这时候就需要使用TO_NUMBER函数,这个函数的语法形式如下:

  1. TO_NUMBER(char[, 'fmt'])

  如表3.11所示,通过一些简单的示例,介绍TO_NUMBER这个函数的使用,其中最后一个示例是先将一个日期类型转换成一个字符类型,再将字符类型转换为数字类型。

表3.11 TO_NUMBER函数示例

函 数 结 果
TO_NUMBER(‘2468’, ‘9999’) 2468
TO_NUMBER(‘2468’, ‘999’) 报错
TO_NUMBER(‘2468’, ‘999999’) 2468
TO_NUMBER(‘246a’, ‘9999’) 报错
TO_NUMBER(TO_CHAR(SYSDATE,’YYYY’),’9999’) 2013

  TO_NUMBER(‘2468’, ‘999’)这个函数报错的原因是格式模板是’999’,要求转换后的数字在-999~999范围之间,而对’2468’使用TO_NUMBER函数,其结果是2468,超过了这个范围,所以报错。TO_NUMBER(‘246a’, ‘9999’)这个函数报错的原因是强制对一个不能转换为数字的字符进行转换。

3.4.4 TO_DATE函数

  在将字符转换为数字时,如果该字符不能转换为数字时会报错;同样的,如果将一个不能转换为日期类型的字符进行强制转换,也会报错。

  将字符类型转换为日期类型,需要使用TO_DATE函数,这个函数的语法形式如下:

  1. TO_DATE(char[, 'fmt'])

  来看一个不带格式模板的简单例子:

  1. SELECT TO_DATE('17-JUN-13') FROM dual

  该SQL语句在PL/SQL Dev上执行,显示的结果是2013/6/17,表明成功转换成日期类型。

  TO_DATE函数的格式模板中可以有一个fx元素,该元素指示对需要转换的字符类型和TO_DATE函数的格式模板必须精确匹配,包括标点符号和空格。来看一个精确匹配的例子:

  1. SELECT TO_DATE('Jan 03, 2006', 'fxMon DD, YYYY') FROM dual

  PL/SQL Dev上执行的结果是2006/1/3,成功转换成日期类型。稍稍调整上面的SQL语句如下(其中第一行是将字符类型中天数的“03”调整为“3”,第二行是将格式模板的“YYYY”后增加了一个空格,第三行是将格式模板的“DD”和“YYYY”之后原来的逗号改成了分号):

  1. SELECT TO_DATE('Jan 3, 2006', 'fxMon DD, YYYY') FROM dual
  2. SELECT TO_DATE('Jan 03, 2006', 'fxMon DD, YYYY ') FROM dual
  3. SELECT TO_DATE('Jan 03, 2006', 'fxMon DD; YYYY') FROM dual

  分别执行这三条SQL语句时都会报错,不能进行转换,可去掉fx这个元素,也就是说不需要再精确匹配。再次执行这三条SQL语句,都能正常显示出2006/1/3的结果。

  假设需要查询雇员表中雇佣日期为2006年1月3日的雇员,显示雇员的名字和雇佣日期信息,其SQL语句如下:

  1. SELECT first_name, hire_date
  2. FROM employees
  3. WHERE hire_date = TO_DATE('Jan 03, 2006', 'fxMon DD, YYYY')

  执行该SQL语句,显示结果如图3.9所示。

3.4 转换函数 - 图3


图3.9 TO_DATE函数

  同样是上面的需求,可以换一个SQL语句的写法,执行结果一样。

  1. SELECT first_name, hire_date
  2. FROM employees
  3. WHERE TO_CHAR(hire_date,'YY/MM/DD') = '06/01/03'

  比较这两个SQL语句,其中第一个在WHERE子句中是将字符类型转换为日期类型,然后将两个日期类型进行比较;而第二个SQL语句则是将日期类型转换为字符类型,将两个字符类型进行比较,其结果是一样的。