Oracle 函数
- 一、SQL函数
- 分类
 
- 二、单行函数
- 字符函数
- 数字函数
- 日期函数
- 转换函数
- to_char
- to_number
- to_date
 
- 其它函数
- 单行函数嵌套
 
- 三、组函数
- 数据分组
- 创建分组
- 过滤分组(having子句)
- 分组和排序
 
- Selecct子句顺序
 
一、SQL函数
函数一般是在数据上执行的,它給数据的转换和处理提供了方便。只是将取出的数据进行处理,不会改变数据库中的值。
 
分类
- SQL函数可以分为组函数和单行函数。
 1、组函数又被称为聚合函数,用于对多行数据进行操作,并返回一个单一的结果,组函数仅可用于选择列表或查询的having子句中。
 2、单行函数是对单个数值进行操作,并返回一个值。
  
二、单行函数

 例:
 查询所有员工的薪水总和
 select sum(sal) from emp;
 
 查看表中有多少条记录
 select deptno,count() from emp group by deptno having count() > 3;
 
字符函数
- 字符函数全以字符作为参数,返回值分为两类:一类返回字符值,一类返回数字值。
例:
 concat: 表示字符串的连接,等同于||
 select concat(‘my name is ‘, ename) from emp;
 
 将字符串的首字母大写
 select initcap(ename) from emp;
 
 将字符串全部转换为大写
 select upper(ename) from emp;
 
 将字符串全部转换为小写
 select lower(ename) from emp;
 
 填充字符串
 向前填充:
 select lpad(ename,10,’‘) from emp;
 
 向后填充:
 select rpad(ename,10,’’) from emp;
 
 去除空格
 trim: 去除 ename 列值的前导和尾随空格,并返回结果集。
 select trim(ename) from emp;
 ltrim: 去除 ename 列值的前导空格,并返回结果集。
 select ltrim(ename) from emp;
 rtrim: 去除 ename 列值的尾随空格,并返回结果集。
 select rtrim(ename) from emp;
 
 查看指定字符串的位置
 select instr(‘ABABCDEF’,‘A’) from emp;
 
 查看字符串的长度
 select length(ename) from emp;
 
 截取字符串的操作
 select substr(ename,0,2) from emp;
 
 替换操作
 select replace(‘ababefg’,‘ab’,‘hehe’) from emp;
 
数字函数
- 数字函数以NUMBER类型为参数返回NUMBER值
例:
 给小数进行四舍五入操作,可以指定小数部分的位数
 select round(123.123,2) from dual;
 
 select round(123.128,2) from dual;
 
 select round(-123.128,2) from dual;
 
 截断数据,按照位数去进行截取,但是不会进行四舍五入的操作
 select trunc(123.128,2) from dual;
 
 取模操作
 select mod(10,4) from dual;
 
 select mod(-10,4) from dual;
 
 向上取整
 select ceil(12.12) from dual;
 
 
 向下取整
 select floor(13.99) from dual;
 
 取绝对值
 select abs(-100) from dual;
 
 获取正负值
 select sign(-100) from dual;
 
 x的y次幂
 select power(2,3) from dual;
 
日期函数
- Oracle以内部数字格式存储日期:世纪,年,月,日,小时,分钟,秒。
例:
 sysdate/current_date: 返回当前的日期
 select sysdate from dual;
 
 select current_date from dual;
 
 add_months: 添加指定的月份
 select add_months(hiredate,2),hiredate from emp;
 
 last_day: 返回输入日期所在月份的最后一天
 select last_day(sysdate) from dual;
 
 months_between: 两个日期相间隔的月份
 select months_between(sysdate,hiredate) from emp;
 
 日期和日期时间算数
 返回四舍五入的第一天
 select sysdate 当时日期,
 round(sysdate) 最近0点日期,
 round(sysdate,‘day’) 最近星期日,
 round(sysdate,‘month’) 最近月初,
 round(sysdate,‘q’) 最近季初日期,
 round(sysdate,‘year’) 最近年初日期 from dual;
 
 返回下周的星期几
 select next_day(sysdate,‘星期一’) from dual;
 
 提取日期中的时间
 select
 extract(hour from timestamp '2001-2-16 2:38:40 ’ ) 小时,
 extract(minute from timestamp '2001-2-16 2:38:40 ’ ) 分钟,
 extract(second from timestamp '2001-2-16 2:38:40 ’ ) 秒,
 extract(DAY from timestamp '2001-2-16 2:38:40 ’ ) 日,
 extract(MONTH from timestamp '2001-2-16 2:38:40 ’ ) 月,
 extract(YEAR from timestamp '2001-2-16 2:38:40 ’ ) 年 from dual;
 
 返回日期的时间戳
 select localtimestamp from dual;
 
 select current_date from dual;
 
 select current_timestamp from dual;
 
 给指定的时间单位增加数值
 select
 trunc(sysdate)+(interval ‘1’ second), --加1秒(1/24/60/60)
 trunc(sysdate)+(interval ‘1’ minute), --加1分钟(1/24/60)
 trunc(sysdate)+(interval ‘1’ hour), --加1小时(1/24)
 trunc(sysdate)+(INTERVAL ‘1’ DAY), --加1天(1)
 trunc(sysdate)+(INTERVAL ‘1’ MONTH), --加1月
 trunc(sysdate)+(INTERVAL ‘1’ YEAR), --加1年
 trunc(sysdate)+(interval ‘01:02:03’ hour to second), --加指定小时到秒
 trunc(sysdate)+(interval ‘01:02’ minute to second), --加指定分钟到秒
 trunc(sysdate)+(interval ‘01:02’ hour to minute), --加指定小时到分钟
 trunc(sysdate)+(interval ‘2 01:02’ day to minute) --加指定天数到分钟 from dual;
 
转换函数
- 标量数据可以有类型的转换,转换分为两种,隐式类型转换和显式类型转换。
 1、隐式转换:指的是字符串可以转换为数值或者日期。
 2、显式转换:to_char:当由数值或者日期转成字符串的时候,必须要规定格式。
注意: 虽然数据类型之间可以进行隐式类型转换,但是仍然建议使用显式转换函数,以保持良好的设计风格。
 
to_char
TO_CHAR函数操作日期
| 格式元素 | 含义 | 
|---|---|
| YYYY、YY | 代表四位、两位数字的年份 | 
| MM | 用数字表示的月份 | 
| MON | 月份的缩写、对中文月份来说就是全称 | 
| DD | 数字表示的日 | 
| DY | 星期的缩写,对中文星期来说就是全称 | 
| HH24,HH12 | 12小时或者24小时进制下的时间 | 
| MI | 分钟数 | 
| SS | 秒数 | 
TO_CHAR(date,‘fmt’)
 用于将日期和时间戳转换成varchar2类型字符串,如果指定了格式字符串,则用它控制结果的结果。
 1、格式控制串由格式元素构成。
 2、格式控制串必须用单引号括起来。
 例:
 select ‘999’ + 10 from dual;
 
 date:to_char
 select to_char(sysdate,‘YYYY-MM-dd HH24:MI:SS’) from dual;
 
 TO_CHAR函数操作数字
| 控制符 | 含义 | 
|---|---|
| 9 | 代表一位数字,如果该位没有数字则不进行显示,但对于小数点后面的部分仍会强制显示 | 
| 0 | 代表一位数字,如果该位没有数字则强制显示0 | 
| $ | 显示美元符号 | 
| L | 显示本地货币符号 | 
| . | 显示小数点 | 
| , | 显示千分位符号 | 
to_char(num,format)
 用于将Number类型参数转换为varchar2类型,如果指定了format,它会控制整个转换。
 例:
 number:to_char
 select to_char(123.456789,‘9999’) from dual;
 
 select to_char(123.456789,‘0000.00’) from dual;
 
 select to_char(123.456789,‘$0000.00’) from dual;
 
 select to_char(123.456789,‘L0000.00’) from dual;
 
 select to_char(123456789,‘999,999,999,999’) from dual;
 
to_number
将char或varchar2类型的string类型转换为number类型
 例:
 to_number: 转成数字
 select to_number(‘123,456,789’,‘999,999,999’) from dual;
 
to_date
将char或varchar2类型的string类型转换为date类型
 例:
 to_date: 转换之后都是固定的格式
 select to_date(‘2022-2-22 22:22:22’,‘YYYY-MM-dd HH24:MI:SS’) from dual;
 
其它函数
条件函数:
 decode,case when
 例: 给不同部门的人员涨薪,10部门的人涨10%,20部门的人涨20%,30部门的人涨30%
 select ename,sal,deptno,decode(deptno,10,sal * 1.1,20,sal * 1.2,30,sal * 1.3) from emp;
 select ename,sal,deptno, case deptno when 10 then sal * 1.1 when 20 then sal * 1.2 when 30 then sal * 1.3 end from emp;
 
单行函数嵌套
- 单行函数可以被嵌入到任何层。
- 嵌套函数从最深层到最低层求值。

 例: 显示员工雇佣期满6个月后下一个星期五的日期
 select hiredate,next_day(add_months(hiredate,6),‘星期五’) from emp;
 
 create table test(
 id number(10) primary key,
 type number(10) ,
 t_id number(10),
 value varchar2(5)
 );
 insert into test values(100,1,1,‘张三’);
 insert into test values(200,2,1,‘男’);
 insert into test values(300,3,1,‘50’);
insert into test values(101,1,2,‘刘二’);
 insert into test values(201,2,2,‘男’);
 insert into test values(301,3,2,‘30’);
insert into test values(102,1,3,‘刘三’);
 insert into test values(202,2,3,‘女’);
 insert into test values(302,3,3,‘10’);
select * from test;
 在Oracle中创建上述表,要求写出一条查询语句结果如下:
 姓名 性别 年龄
 ——————
 张三 男 50
 我们可以使用decode函数来解决此问题:
 select decode(type, 1, value) 姓名,decode(type, 2, value) 性别,decode(type, 3, value) 年龄 from test;
 
 由上述结果图可以发现和我们想要的结果不太一样,表中多了很多空行,这时我们可以对sql语句进行优化得到下面的结果。
 select max(decode(type, 1, value)) 姓名,max(decode(type, 2, value)) 性别,max(decode(type, 3, value)) 年龄 from test group by t_id;
 
 这是我们发现和想要的结果是一样的,但是还发现优化后的sql语句中多了max,上面单行函数好像没说max函数,所以接下来我们就要引入组函数的概念。
三、组函数
组函数基于多行数据返回单个值。
 注意: 组函数,一般情况下,组函数都要和group by组合使用,还可用于选择列表或者having条件判断。
 常用的组函数有五个:
avg(): 平均数,只适用于数值类型的数据。
min() : 最小值,适用于任何类型。
max() : 最大值,适用于任何类型。
count(): 记录数,处理的时候跳过空值而处理非空值,一般用来获取表中的记录条数,获取条数的时候可以使用 * 或者某一个具体的列,甚至可以使用纯数字来代替,但是从运行效率的角度考虑,建议使用数字或者某一个具体的列而不要使用 * 。
sum() : 求和,只适用于数值类型的数据。
例:
 avg: select avg(sal) from emp;
 
 min: select min(sal) from emp;
 
 max: select max(sal) from emp;
 
 count: select count(sal) from emp;
 
 sum: select sum(sal) from emp;
 
 特别注意,组函数是不能处理null,必须使用NVL函数迫使组函数包括空值。
数据分组
创建分组
- group by子句按照某些相同的值去分组操作。
- 除组函数语句外,select语句中的每个列都必须在group by子句中给出。
- 如果分组列中具有null值,则null值将作为一个分组返回。如果列中有多行null值,他们将分为一组。
- group by子句必须出现在where子句之后,order by子句之前 。
过滤分组(having子句)
- Where过滤行,having过滤分组。
- Having支持所有where操作符。
分组和排序
一般在使用group by子句时,应该也给出order by子句。
 例:
 求每个部门的平均薪水
 select avg(sal) from emp group by deptno;
 
 求平均薪水大于2000的部门
 select avg(sal),deptno from emp group by deptno having avg(sal) > 2000;
 
- 出现在SELECT列表中的字段,如果出现的位置不是在组函数中,那么必须出现在GROUP BY子句中。
- 不能在WHERE子句中使用组函数;不能在WHERE子句中限制组;使用Having对分组进行限制。
例:
 求部门下雇员的工资>2000的人数
 select deptno,count(1) from emp where sal > 2000 group by deptno;
 
 求部门薪水最高的人
 select deptno,max(sal) from emp group by deptno;
 
 求部门的平均薪水仅包括平均工资大于1000的部门
 select deptno,avg(sal) from emp group by deptno having avg(sal) > 1000;
 
Selecct子句顺序
| 子句 | 说明 | 是否必须使用 | 
|---|---|---|
| select | 要返回的列或表达式 | 是 | 
| from | 从中检索数据的表 | 仅在从表中选择数据时使用 | 
| where | 行级过滤 | 否 | 
| group by | 分组说明 | 仅在按组计算聚集时使用 | 
| having | 组级过滤 | 否 | 
| order by | 输出排序顺序 | 否 | 
Sql语句执行过程:
- 读取from子句中的基本表、视图的数据,[执行笛卡尔积操作]。
- 选取满足where子句中给出的条件表达式的元组。
- 按group by子句中指定列的值分组,同时提取满足having子句中组条件表达式的那些组。
- 按select子句中给出的列明或列表达式求值输出。
- order by子句对输出的目标表进行排序。