Oracle函数、子程序实例讲解

子程序

一、子程序概述

pl/sql命名程序块的定义在pl/sql程序块的声明部分,用户称之为子程序。

通俗讲:命名的 pl/sql 块,编译并存储在中。

子程序构成:

l 声明部分

l 可执行部分

l 异常处理部分(可选)

子程序的优点:

模块性:子程序可以将程序划分成易于管理,定义明确的逻辑模块,它支持自顶向下的设计方法。

可维护性:简化维护操作。

可重性:子程序一旦被定义可以用于许多个应用程序。

安全性:通过设置权限,使数据更安全。

二、子程分类

oracle提供了4种类型的子程序:存储过程、函数、包、触发器。

过程 - 执行某些操作

函数 - 执行操作并返回值

三、子程序之:函数

函数是可以返回值的命名的 pl/sql 子程序。

函数分为:内置函数 和 自定义函数。

1. 内置函数

由oracle提供的一系列用于执行特定操作的函数。

sql内置函数带有一个或多个参数并返回一个值。

sql内置函数分为:单行函数、分组函数、分析函数

l 单行函数:从表中查询的每一行只返回一个值。

日期函数,数字函数,字符函数,转换函数,其他函数

l 分组函数:基于一组行来返回结果。为每一组行返回一个值。

count()、sum()、avg()、max()、min()

l 分析函数:根据一组行来计算聚合值。用于计算完成聚集的累计排名、移动平均数等。

分析函数为每组记录返回多个行。

row_number、rank、dense_rank

1.1 数值函数

round() 四舍五入

select round( 10054.345 ) from dual;

–返回:10054

select round( 10054.345 , 2 ) from dual;

–返回:10054.35 精确到小数点后2位

select round( 10054.345 , -2 ) from dual;

–返回:10100

trunc() 取整(无四舍五入)

select trunc( 45.67 ) from dual;

–返回:45

select trunc( -45.22 , 0 ) from dual;

–返回:-45

floor() 取整(最小值,无四舍五入)

select floor( 45.67 ) from dual;

–返回:45 最小的整数

select floor(-45.17) from dual;

–返回:-46 最小的负整数

mod() 求模(与java中的%一样)

select mod( 11 , 7) from dual;

–返回:4

power() 开方

select power( 5 , 2 ) from dual;

–返回:25 求5的2次方

sqrt() 开根号

select sqrt( 4 ) from dual;

–返回:2

sign()判断值的正负数

–正数返回1,0返回0,负数返回-1(以后常用)

select sign( 10 ) from dual;

–返回:1

1.2 字符函数

substr() 字符串截取

select substr( ‘abcdefg’ , 2 , 4 ) from dual;

–返回:bcde 从第2位开始连续截取4个

–注意:sql和oracle中字符串角标是从1开始;而java中字符串角标是从0开始。

length() 求字符串长度(字符个数,与中英文所占字节无关)

select length( ‘abc’ ) from dual;

–返回:3

instr() 查找字符位置(类似于java中的charindex,sql server中的indexof)

select instr( ‘abcadefag’ , ‘a’ ) from dual;

–返回:1 默认从字符串角标1开始查找

select instr( ‘abcsadefag’ , ‘a’ , 4 ) from dual;

–返回:5 从字符串角标4开始查找

concat() 连接 与||相同

select concat(‘a’,’b’) from dual;

–结果:ab

replace() 替换

select replace(‘abcdefg’,’a’,9) from dual;

–结果:9bcdefg

select translate(‘adbecf’,’abc’,’123′) from dual;

lpad() 左填充

select lpad(‘abc’,10,’6′) from dual; –10是字符串总长度

–结果:6666666abc

rpad() 右填充

select rpad(‘abc’,10,’6′) from dual;

–结果:abc6666666

trim()

–有两个意思:去除字符串两边的空格

— 去除字符串两边指定的字符

–语法:trim(‘字符1’ from ‘字符串2’)

select trim(‘a’ from ‘aabbbccdda’) from dual;

–结果:bbbccdd

chr() ascii码对应的字符

select chr(97) from dual;

–结果:a

ascii() 字符对应的ascii码

select ascii(‘a’) from dual;

–结果:97

decode()

–decode(value,if1,then1,if2,then2,if3,then3,…,else)

表示如果value 等于if1时,decode函数的结果返回then1,…,如果不等于任何一个if值,则返回else。初看一下,decode()只能做等于测试,但刚才也看到了,我们通过一些函数或计算替代value,是可以使decode()函数具备大于、小于或等于功能。

select decode(‘a’,’a’,1,’b’,2,’c’,3) from dual;

–1

–工资大于3500提示交税,等于3500刚刚好,小于3500要努力

–分析:三种情况

select decode(sign(sal-3500),1,’交税’,0,’刚好’,-1,’努力’) from emp;

1.3 日期函数

sysdate 取当前时间

select sysdate from dual;

–显示时间类型(date),但要转成字符串呢?

systimestamp 获取系统当前时间

select systimestamp from dual;

–结果比较长,格式是格林乔治时间

add_months() 取月份实现加月份

select add_months(sysdate,3) from dual;

–在当前系统时间月份上加3

select add_months(to_date(‘2015-12-12′,’yyyy-mm-dd’),3) from dual;

–在2015-12-12的月份上加3

extract() 取(年月日)

select extract(day from sysdate) from dual;

–取当前系统的日

select extract(month from sysdate) from dual;

–取当前系统的月

–案例:求每个月的入职人数

按月分组统计

select extract(month from hiredate),count(*) from emp

group by extract(month from hiredate)

–求每年每个月的入职人数

select extract(year from hiredate),extract(month from hiredate),count(*) from emp

group by extract(year from hiredate),extract(month from hiredate)

months_between() 时间差

select months_between(sysdate,to_date(‘2015-12-12′,’yyyy-mm-dd’)) from dual;

–前面的日期减去后面的日期,返回是月份,会出现负数,也会出现小数(最精确的)

last_day() 取本月的最后一天

select last_day(sysdate) from dual;

–2016/2/29 16:59:13 本月最后一天的当前时间

next_day() 下一个日期

select next_day(sysdate,’星期四’) from dual;

–结果:下一个“星期四”的日期

问:下一周的星期三和下一个星期三是一样的吗?

round() 取最近的一天

–取整,超过12点算第二天,有四舍五入功能

select round(to_date(‘2009-09-08 12:12:12′,’yyyy-mm-dd hh:mi:ss’)) from dual;

–只取整数部分 2009/9/9 还有超过12点就算9号了

select round(to_date(‘2009-09-08 12:12:12′,’yyyy-mm-dd hh24:mi:ss’)) from dual;

–只取整数部分 2009/9/9

trunc() 截取日期函数

–取整,当天

select trunc(to_date(‘2009-09-08 12:12:12′,’yyyy-mm-dd hh:mi:ss’)) from dual;

–只取整数部分 2009/9/8

select trunc(to_date(‘2009-09-08 23:12:12′,’yyyy-mm-dd hh24:mi:ss’)) from dual;

–只取整数部分 2009/9/8

1.4 转换函数

转换函数将值从一种数据类型转换为另一种数据类型。

to_char

将非char类型转成char类型

select to_char(sysdate,’yyyy-mm-dd’) from dual;

select to_char(sysdate,’yyyymmdd’) from dual;

select to_char(sysdate,’yyyy”年”mm”月”dd”日”‘) from dual;

–这是oracle中唯一用到双引号的地方

to_date

将非date类型转成date类型

select to_date(‘2016-09-09′,’yyyy-mm-dd’) from dual;

select to_date(‘2016-09-09 18:20:30′,’yyyy-mm-dd hh24:mi:ss’) from dual;

to_number

将非数值型转成数值型

select to_number(‘345’) from dual;

select to_number(’34a5′) from dual;

1.5 集合函数

count()

sum()

avg()

max()

min()

1.6 其他函数

转换空值函数

nvl(exp1,exp2)

–如果oracle第一个参数为空那么显示第二个参数的值,如果第一个参数的值不为空,则显示第一个参数本来的值。

select ename,nvl(comm, -1) from emp;

nvl2(exp1,exp2,exp3)

–如果该函数的第一个参数为空那么显示第三个参数的值,如果第一个参数的值不为空,则显示第二个参数的值。

select ename,nvl2(comm,-1,1) from emp;

nullif(exp1,exp2)

–如果exp1和exp2相等则返回空(null),否则返回第一个值。

select ename,nullif(comm,-1) from emp;

1.7 分析函数

7. 分析函数

主查询结果的基础上进行一定的分析,如分部门汇总,分部门求均值等等。

(1)oracle 分析函数建立在所谓的数据窗口之上,数据窗口可以理解为一个数据集合。

主查询的数据可以按照不同的标准分割成不同的数据集。

比如partition by manager_id,按照manager_id将主查询的数据分成n(n代表有多少个不同的manager_id)个不同的数据窗口。

(2)其次,数据窗口内部还应该与一定的顺序通过 order by 实现

row_number() over()

rank() over()

dense_rank() over()

分析函数和group by的区别和联系:

(1)分析函数的功能大部分都可以通过group by 来聚合完成

(2)分析函数查询出来的行数是由主查询决定的,group by 的行数结果是由group by 后面的集合构成的唯一性组合决定的,通常比主查询的结果行数少。

sum(emp.salary) over(partition by emp.manager_id) sum_salary_department, –该部门薪水总额

dense_rank() over(partition by emp.manager_id order by emp.salary desc) rank_salary_dept, –该人员的部门薪水排行

min(emp.salary) keep(dense_rank first order by emp.salary) over(partition by emp.manager_id) min_salary_dept_first, –部门的最低薪水

first_value(emp.salary) over(partition by emp.manager_id order by emp.salary) min_salary_dept_firstv, –部门的最低薪水

lag(emp.full_name, 1, ’00’) over (order by emp.salary desc) last_persion, –薪水在自己前一位的人

2. 自定义函数

2.1 创建函数(in、out、in out)

创建函数的语法:

create [or replace] function

[(param1,param2)]

return is|as

[local declarations]

begin

executable statements;

return result;

exception

exception handlers;

end;

–案例:给编号,返回工资’交税’还是’刚好’,还是’努力’

create or replace function f_n126(sid number)

return varchar2

is

ssal number(8,2);

str varchar2(22); –注意,该处不用declare定义

begin

select sal into ssal from emp where empno=sid;

if ssal>3500 then

str:=’交税’;

elsif ssal=3500 then

str:=’刚好’;

else

str:=’努力’;

end if;

return str;

end;

create or replace function my_sum(n_a in number)

return number

is

n_sum number(5):=0;

begin

for int_s in 1..n_a loop

n_sum:=n_sum+int_s;

end loop;

return n_sum;

end;

定义函数的限制:

  函数只能接受 in 参数,而不能接受 in out 或 out 参数

  形参不能是 pl/sql 类型

  函数的返回类型也必须是数据库类型

访问函数的两种方式:

  使用 pl/sql 块

  使用 sql 语句

创建函数

create or replace function fun_hello

return varchar2

is

begin

return ‘朋友,您好’;

end;

从 sql 语句调用函数:

select fun_hello from dual;

create or replace function

item_price_range (price number)

return varchar2 as

min_price number;

max_price number;

begin

select max(itemrate), min(itemrate)

into max_price, min_price

from itemfile;

if price >= min_price and price <= max_price

then

return ‘输入的单价介于最低价与最高价之间’;

else

return ‘超出范围’;

end if;

end;

declare

p number := 300;

msg varchar2(200);

begin

msg := item_price_range(300);

dbms_output.put_line(msg);

end;

2.2 调用函数

–oracle调用方式:

select f_n126(7369) from dual;

–pl/sql调用方式:

declare str varchar2(22);

begin

str:=f_n126(7369);

dbms_output.put_line(str);

end;

2.3 删除函数

drop function f_name; 

(0)
上一篇 2022年3月22日
下一篇 2022年3月22日

相关推荐