Oracle数据库五类单行函数讲解及习题解析
虽然各个数据库都是支持SQL语句的,但是每一个数据库也有每一个数据库自己所支持的操作函数,这些就是单行函数,而如果要想进行数据库开发的话,除了要会使用SQL之外 ,就是要多学习函数。
单行函数主要分为以下五类:字符函数、数字函数、日期函数、转换函数、通用函数;
一、字符函数
字符函数的功能主要是进行字符串数据的操作,下面给出几个字符函数:
UPPER(字符串 | 列):将输入的字符串变为大写返回; LOWER(字符串 | 列):将输入的字符串变为小写返回; INITCAP(字符串 | 列):开头首字母大写; LENGTH(字符串 | 列):求出字符串的长度; REPLACE(字符串 | 列):进行替换; SUBSTR(字符串 | 列,开始点 [,截取的个数]):字符串截取; 1、转大写的函数 SELECT UPPER('hello') FROM dual;
2、转小写的操作,将所有的雇员姓名按照小写字母返回
SELECT LOWER(ename) FROM emp;
3、将每一个雇员姓名的开头首字母大写
SELECT INITCAP(ename) FROM emp;
4、查询出每个雇员姓名的长度
SELECT ename,LENGTH(ename) FROM emp;
5、要求查询出姓名长度正好是5的雇员信息
SELECT ename,LENGTH(ename) FROM emp
WHERE LENGTH(ename)=5;
6、使用字母“_”替换掉姓名中的所有字母“A”
SELECT REPLACE(ename,'A','_') FROM emp;
7、字符串截取操作有两种语法:
语法一:SUBSTR(字符串 | 列,开始点),表示从开始点一直截取到结尾;
SELECT ename,SUBSTR(ename,3) FROM emp;
语法二:SUBSTR(字符串 | 列,开始点,结束点),表示从开始点截取到结束点,截取部分内容;
SELECT ename,SUBSTR(ename,0,3) FROM emp;
7.1、要求截取每个雇员姓名的后三个字母
正常思路:通过长度-2确定开始点
SELECT ename,SUBSTR(ename,LENGTH(ename)-2) FROM emp;
新思路:设置负数,表示从后指定截取位置;
SELECT ename,SUBSTR(ename,-3) FROM emp;
二、数字函数
数字函数一共有三个:
ROUND(数字 | 列 [,保留小数的位数]):四舍五入的操作; TRUNC(数字 | 列 [,保留小数的位数]):舍弃指定位置的内容; MOD(数字 1,数字2):取模,取余数;
1、SELECT ROUND(903.53567),ROUND(-903.53567), ROUND(903.53567,2),ROUND(-90353567,-1) FROM dual;
上述查询语句的查询结果是:
904 -904 903.54 -90353570
2、
SELECT TRUNC(903.53567),TRUNC(-903.53567),TRUNC(903.53567,2), TRUNC(-90353567,-1) FROM dual;
上述查询语句的查询结果是:
903 -903 903.53 -90353560
3、SELECT MOD(10,3) FROM dual;
上述查询语句的查询结果是:1
三、日期函数
如果现在要想进行日期的操作,则首先有一个必须要解决的问题,就是如何取得当前的日期,这个当前日期可以使用“SYSDATE”取得,代码如下:
SELECT SYSDATE FROM dual;
除了以上的当前日期之外,在日期中也可以进行若干计算:
日期 + 数字 = 日期,表示若干天之后的日期;
SELECT SYSDATE + 3,SYSDATE+ 300 FROM dual;
日期 – 数字 = 日期,表示若干天前的日期;
SELECT SYSDATE - 3,SYSDATE- 300 FROM dual;
日期 – 日期 = 数字,表示的是两个日期间的天数,但是肯定是大日期 – 小日期;
范例:求出每个雇员到今天为止的雇佣天数
SELECT ename,hiredate,SYSDATE-hiredate FROM emp;
而且很多的编程语言之中,也都会提出一种概念,日期可以通过数字表示出来。
除了以上的三个公式之外,也提供了如下的四个操作函数:
LAST_DAY(日期):求出指定日期的最后一天;
范例:求出本月的最后一天日期
SELECT LAST_DAY(SYSDATE) FROM dual;
NEXT_DAY(日期,星期数):求出下一个指定星期X的日期;
范例:求出下一个周一
SELECT NEXT_DAY(SYSDATE,'星期一') FROM dual;
ADD_MONTHS(日期,数字):求出若干月之后的日期;
范例:求出四个月后的日期
SELECT ADD_MONTHS(SYSDATE,4) FROM dual;
MONTHS_BETWEEN(日期1,日期2):求出两个日期之间所经历的月份;
范例:求出每个雇员到今天为止的雇佣月份
SELECT ename,hiredate,TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)) FROM emp;
在所有的开发之中,如果是日期的操作,建议使用以上的函数,因为这些函数可以避免闰年的问题。
四、转换函数
现在已经接触到了Oracle数据库之中的三种数据:数字(NUMBER)、字符串(VARCHAR2)、日期(DATE),转换函数的主要功能是完成这几种数据间的互相转换操作,一共有三种转换函数:
TO_CHAR(字符串 | 列,格式字符串):将日期或者是数字变为字符串显示; TO_DATE(字符串,格式字符串):将字符串变为DATE数据显示; TO_NUMBER(字符串):将字符串变为数字显示;
a、TO_CHAR()函数
在之前查询过当前的系统日期时间:
SELECT SYSDATE FROM dual;
这个时候是按照“日-月-年”的格式显示,很明显这种显示格式不符合正常的思路,正常是“年-月-日”,所以这种情况下可以使用TO_CHAR()函数,但是使用此函数的话需要一些格式字符串:年(yyyy),月(mm),日(dd)。
SELECT TO_CHAR(SYSDATE,'yyyy-mm-dd'),TO_CHAR(SYSDATE,'yyyy') year,TO_CHAR(SYSDATE,'mm') month,TO_CHAR(SYSDATE,'dd') dayFROM dual;
上述运行结果是:
2017-08-12 2017 08 12
但是这个时候的显示数据之中可以发现会存在前导0,如果要想消除掉这个0的话,可以加入一个“fm”。
SELECT TO_CHAR(SYSDATE,'fmyyyy-mm-dd') day FROM dual;
运行结果为:2017-8-12
SELECT TO_CHAR(SYSDATE,'fmyyyy-mm-dd hh24:mi:ss')day FROMdual;
上述运行结果为:2017-8-12 16:13:38
b、TO_DATE()函数
此函数的主要功能是将一个字符串变为DATE型数据。
SELECT TO_DATE('1989-09-12','yyyy-mm-dd') FROMdual;
12-9月 -89
五、通用函数
通用函数主要有两个:NVL()、DECODE(),这两个函数算是Oracle自己的特色函数了;
a、NVL()函数,处理null
b、DECODE()函数:多数值判断
DECODE()函数非常类似于程序中的if…else…语句,唯一不同的是DECODE()函数判断的是数值,而不是逻辑条件。
例如,现在要求显示全部雇员的职位,但是这些职位要求替换为中文显示:
CLERK:办事员; SALESMAN:销售; MANAGER:经理; ANALYST:分析员; PRESIDENT:总裁;
这种判断肯定是逐行进行判断,所以这个时候就必须采用DECODE(),而此函数的语法如下:
DECODE(数值 | 列 ,判断值1,显示值1,判断值2,显示值2,判断值3,显示值3,…)
范例:实现显示的操作功能
SELECT empno,ename,job,DECODE(job,'CLERK','办事员','SALESMAN','销售人员','MANAGER','经理','ANALYST','分析员','PRESIDENT','总裁') FROM emp;
DECODE()函数是整个Oracle之中最具特点的函数,一定要将其掌握。
习题讲解
1、 选择部门30中的所有员工。
SELECT * FROMemp WHERE deptno=30;
2、 列出所有办事员(CLERK)的姓名,编号和部门编号。
SELECT empno, ename, deptno FROM emp WHERE job='CLERK';
3、 找出佣金高于薪金的员工。
SELECT * FROMemp WHERE comm>sal;
4、 找出佣金高于薪金的60%的员工。
SELECT * FROMemp WHERE comm>sal*0.6;
5、 找出部门10中所有经理(MANAGER)和部门20中所有办事员(CLERK)的详细资料。
SELECT * FROM emp
WHERE (job='MANAGER' AND deptno=10) OR (job='CLERK' AND deptno=20);
6、 找出部门10中所有经理(MANAGER),部门20中所有办事员(CLERK),既不是经理又不是办事员但其薪金大于或等于2000的所有员工的详细资料。
SELECT * FROM emp
WHERE (job='MANAGER' AND deptno=10) OR (job='CLERK' AND deptno=20)
OR (job NOT IN ('MANAGER','CLERK') AND sal>=2000);
7、 找出收取佣金的员工的不同工作。
SELECT DISTINCT job FROMemp WHERE comm ISNOT NULL;
8、 找出不收取佣金或收取的佣金低于100的员工。
SELECT * FROMemp WHERE comm ISNULL OR comm<100;
9、 找出各月倒数第3天受雇的所有员工。
每一个雇员的雇佣日期肯定是不一样的,所以现在必须找到每一个雇员雇佣所在月的最后一天,之后按照“日期-数字”的方式求出前三天的日期,这个日期必须和雇佣日期相符合才满足条件。
SELECT * FROMemp WHERE LAST_DAY(hiredate)-2=hiredate;
10、 找出早于12年前受雇的员工。
如果要求年份,最准确的做法是使用总月数/12;
SELECT * FROMemp WHERE MONTHS_BETWEEN(SYSDATE,hiredate)/12>12;
11、 以首字母大写的方式显示所有员工的姓名。
SELECT INITCAP(ename) FROM emp;
12、 显示正好为5个字符的员工的姓名。
SELECT ename FROM emp WHERELENGTH(ename)=5;
13、 显示不带有“R”的员工的姓名。
SELECT ename FROM emp WHEREename NOT LIKE '%R%';
14、 显示所有员工姓名的前三个字符。
SELECT SUBSTR(ename,0,3) FROM emp;
15、 显示所有员工的姓名,用“a”替换所有“A”。
SELECT REPLACE(ename,'A','a') FROM emp;
16、 显示满10年服务年限的员工的姓名和受雇日期。
SELECT ename, hiredate FROM emp
WHEREMONTHS_BETWEEN(SYSDATE,hiredate)/12>10;
17、 显示员工的详细资料,按姓名排序。
SELECT * FROMemp ORDER BYename;
18、 显示员工的姓名和受雇日期,根据其服务年限,将最老的员工排在最前面。
SELECT ename, hiredate FROM emp ORDER BY hiredate;
19、 显示所有员工的姓名、工作和薪金,按工作的降序排序,若工作相同则按薪金排序。
SELECT ename, job, sal FROM emp ORDER BY job DESC,sal;
20、 显示所有员工姓名、加入公司的年份和月份,按受雇日期所有月排序,若月份相同则将最早年份的员工排在最前面。
本程序需要从日期之中取出年份和月份,用TO_CHAR()函数完成。
SELECT ename,TO_CHAR(hiredate,'yyyy') year,TO_CHAR(hiredate,'mm') months
FROM emp
ORDER BY months,year;
21、 显示在一个月为30天的情况所有员工的日薪金,忽略余数。
SELECT ename,sal,TRUNC(sal/30) FROM emp;
22、 找出在(任何年份的)2月受聘的所有员工。
SELECT * FROMemp WHERE TO_CHAR(hiredate,'mm')=2;
23、 对于每个员工,显示其加入公司的天数。
SELECT ename,SYSDATE-hiredate FROM emp;
24、 显示姓名字段的任何位置包含“A”的所有员工的姓名。
SELECT ename FROM emp WHEREename LIKE '%A%';
25、 以年月日的方式显示所有员工的服务年限。
第一步:求出每个雇员的雇佣年数:被雇佣的总月数 / 12 = 年数;
SELECT ename, hiredate,
TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12) year
FROM emp;
第二步:求出月数,以上计算之中被忽略的小数点实际上都是月份,所以直接取余即可;
SELECT ename, hiredate,
TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12) year,
TRUNC(MOD(MONTHS_BETWEEN(SYSDATE,hiredate),12)) months
FROM emp;
第三步:求出天数,最准确的做法是在不超过30天的范围之内求;
现在已经知道当前的时间使用SYSDATE取出,而雇佣的日期使用hiredate取出,可是hiredate和SYSDATE之间的差距太大了,所以肯定会有误差,那么就必须想办法将hiredate的日期提升到与SYSDATE差距在30天的范围之内。
在之前学习过两个函数:
MONTHS_BETWEEN():求出两个日期间的月数,如果是:MONTHS_BETWEEN(SYSDATE,hiredate)求出的是雇佣日期到今天为止的雇佣月份; ADD_MONTHS():在一个日期上加入指定的月之后的日期,如果说hiredate + 与今天相距的月数 = 一个新的日期,而且这个新的日期肯定和SYSDATE相距不超过30天。
SELECT ename, hiredate,
TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12) year,
TRUNC(MOD(MONTHS_BETWEEN(SYSDATE,hiredate),12)) months,
TRUNC(SYSDATE-ADD_MONTHS(hiredate,MONTHS_BETWEEN(SYSDATE,hiredate)))day
FROM emp;
以上的这道程序,属于日期函数的综合应用。
上一篇: Oracle学习笔记(优质内容)
下一篇: MySQl与Oracle数据库的对比