欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Oracle数据库五类单行函数讲解及习题解析

程序员文章站 2022-06-24 20:24:27
虽然各个数据库都是支持SQL语句的,但是每一个数据库也有每一个数据库自己所支持的操作函数,这些就是单行函数,而如果要想进行数据库开发的话,除了要会使用SQL之外 ,就是要多学习函数...

虽然各个数据库都是支持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;

以上的这道程序,属于日期函数的综合应用。