plsql(轻量版)-存储函数&存储过程

ORACLE提供可以把PL/SQL程序存储在数据库中,并可以在任何地方运行他,这样就叫做存储过程或者函数,

意思就说白了,就是你之前写的select,什么update,这些东西存储起来,我想把这些操作存储起来,像表,

视图,结构式的,当然他不是对象,这里不叫对象,他也能够存储起来,像Function,这是系统提供的,你自己创建的,

之前写过,我们可以删掉他,这儿说明他确确实实存在,包括像这个触发器,这里没有,说明没有创建,当你创建一个

函数,存储过程的时候,那就能够保存下来,什么时候想调用,就调用就完了,触发器,当你想对某个表进行操作的时候,

也是类似于一个函数的东西,这个时候叫做触发器,自动的触发他,就是这样,它是可以被保存起来的,过程和函数的唯一

区别就是函数总是向调用者返回数据,而过程不返回数据,相当于一个有返回值,一个没有,函数是有的,过程是没有的

创建create or replace function,跟前面写的视图都一样,然后这个function的名,如果有参数的话,后边写上

他整个的参数类型,这相当于是一个小括号,function涉及到的形参一样,形参你写到这里边,先写一个参数名,再写参数类型,

这里就不需要指定一个参数的大小了,仅仅是几个类型就行,这个形参什么时候给你填进去,就是通过declare语句,我们上午讲了

declare,begin,在begin;里面调用这个函数的时候,参数是什么,return紧接着就是你返回函数的返回值类型,然后这个叫is,

is里面操作的你可以把它假象成,加上declare,函数在整个的使用当中,你需要定义一个变量,你就定义到这儿,再是你这个函数的

执行体,如果有异常的话,我给你写的这个结构,函数的结构

存储函数,这个结构怎么写,他就是create or replace function,取个function名,就写func_name,

括号写上你参数的类型,参数类型,id number类型的,逗号,name,你想查指定表当中的id,这个id,这个名字的

那个人,等等,或者你想查一下id这个人的工资,salary也是number类型的,往那放,这里又具体分,讲什么out,

一会说到这再说,这是定义这个函数,然后他return,返回值类型,假设你要返回,这里不写这个id,写dept_id,

我返回指定部门的,所有的工资,指定部门可能有很多人,这些所有人的工资,return也是工资,工资是number类型的,

你就返回number类型的,然后is,你在这个过程当中,是不是再涉及到你要定义一些变量,如果需要的话,你写在is这一块,

就是函数的使用过程中,需要声明的变量,或者叫记录类型,写在这,声明一个变量,记录类型,甚至还可以是游标,游标就

写在这,然后呢,begin,开始,这是函数的执行,函数的执行体,在这个过程当中,出现一个异常,考虑异常的处理,处理函数

处理过程中的异常,处理完了以后,就给他end,这是存储函数的一个过程,这里相当于declare,我们写一个PL/SQL的时候,

declare begin end,你就把他当成declare,就是在声明函数中调用到的变量,这是函数的一个形参,这样创建好以后,他就有

这个了,有这个function以后,大概形式就是这样

create or replace function func_name(dept_id number,salary number)

return number;

is

begin

exception

end;

22.2 返回一个"helloworld: atguigu"的字符串,其中atguigu 由执行函数时输入。

--函数的声明(有参数的写在小括号里)
create or replace function hello_func(v_logo varchar2)
--返回值类型
return varchar2
is 
--PL/SQL块变量的声明
begin
--函数体
       return 'helloworld'|| v_logo;
end;

这就是这个函数的作用,函数的helloworld,调用这个函数就返回hellworld,看他怎么写,create or replace function,

叫hello_world,这个函数没有形参,返回helloworld这个字符串,return varchar2,不用写那个什么,不用写分号,也不用写大小,

is声明,也不用声明,直接begin,return,这是你函数的执行体,执行后的结果,因为你这个函数是需要有返回值的,我就在这里给你

返回,没有异常,没有就end,这是一个最简单的存储函数,创建了

create or replace function hello_world

is

begin

	return "helloworld";

end;

创建以后我们在这看,这里就有一个hello_world

正常来写,declare什么什么,这里也不用declare,直接begin,dbms_output.put_line,调用你hello_world

这个函数,end,这就出来了

begin

	dbms_output.put_line(hello_world);
	
end;

或者你在这使用select语句也行,select hello_world,from dual

select hello_world from dual;

这就是具体调用这个函数了,这是这个例子,然后我把它写得复杂一点,给这个函数带上一个参数,hello_world1,

带个参数,什么参数,加上一个v_log,它是一个varchar2类型的,返回他这个varchar2,然后is是声明,声明写到这里也行,

变量的声明,这里不需要变量声明,这个变量已经有了不需要声明,begin,v_log他赋一个值,直接return,这里我定义了

一个形参,相当于,然后呢走到这,创建好了

create or replace function hello_world1(v_logo varchar2)

return varchar2

is

begin

	return 'helloworld' || v_logo;
	
end;

然后这个调用,select就这么写,select hello_world1,这个参数,varchar型的,他,from他

select hello_world1('atguigu') from dual;

这是select,如果你想使用PL/SQL句型的话,那你就这样

begin

	dbms_output.put_line(hello_world('atguigu'));
	
end;

一种是使用PL/SQL程式的形式,一种是SELECT的形式,关键是你要会写这个,这个格式,创建一个函数,函数名,

函数是否需要参数,需要的话就需要写上一个参数,参数的话只要指明类型就行,函数一定是有返回值的,一定会

return一个东西,然后函数在使用过程中,是否需要声明一些变量,相当于在JAVA里边,方法里边,局部变量,起在

is和begin之间,你也可以把它理解成declare,我们之前写在declare和begin之间的东西可以写在这儿,begin,你这个

函数具体执行的函数体,结束,一定要记住这,那这儿你也可以加上一个输出语句,这里or replace相当于把它替换了

create or replace function hello_world1(v_logo varchar2)

return varchar2

is

begin

	dbms_output.put_line('人家是函数啦,么么哒');
	
	return 'helloworld' || v_logo;
	
end;

select hello_world1('atguigu1') from dual;

就相当于他执行这个函数体,你这个传入的就放到这儿了,跟你讲JAVA的情况一样,实际上你声明一个值,给我

传一个值,调用你传入的这个值,就是这个意思,这个你看返回的这个顺序,你看它是先输出的这个,再打印的这个,

因为它是有返回值的,他select先拿到你这个返回值,然后返回完了以后,你要这样写的话,或者说有两种执行方式,

另一种

begin

dbms_output.put_line(hello_world1('atguigu'));

end;

这个先输出的这个,是按照你的顺序,这个你了解一下就行,重点是你如何来定义这个函数,

这个函数就这样,然后我们看别的例题

22.3 创建一个存储函数,返回当前的系统时间
create or replace function func1
return date
is
--定义变量
v_date date;
begin
	--函数体
	--v_date := sysdate;
       select sysdate into v_date from dual;
       dbms_output.put_line('我是函数哦');
       
       return v_date;
end;

执行法1:
select func1 from dual;
执行法2:
declare
  v_date date;
begin
  v_date := func1;
  dbms_output.put_line(v_date);
end;

创建一个存储函数,返回当前的系统时间,这个就是函数的作用,create or replace function,get_sysdate,这是他的

函数名,return是一个date类型的,然后is需要声明变量吗,声明一个也行,声明一下就这样,date类型的,这个不需要指明大小,

begin,可以这样写,v_date := sysdate,然后呢,然后return date,没有异常,直接end,这样写

create or replace function get_sysdate

return date

is

	v_date date;
	
begin

	v_date := sysdate;
	
	return v_date;
	
end;

然后你在这执行一个

select get_sysdate from dual;

23. 定义带参数的函数: 两个数相加

create or replace function add_func(a number, b number)
return number
is
begin
       return (a + b);
end;

执行函数

begin
    dbms_output.put_line(add_func(12, 13));
end;
或者
    select add_func(12,13) from dual;
	
定义带参数的函数,create or replace function,add,add相加的意思,两个参数相加,定义v_num1,number类型的,

v_num2,还是number类型,return返回number类型的,is需要再声明一个变量不,v_sum计算他们的和,number类型的,

指明10个,begin,v_sum等于v_num1加上v_num2,return v_sum

create or replace function add add_param(v_num1 number,v_num2 number)

return number

is
	
	v_sum number(10);
	
begin

	v_sum := v_num1 + v_num2;
	
	return v_sum;
	
end;

创建好了,这个,运行一下

select add_param(2,4) from dual;

在这也行,这个就是使用PL/SQL块的形式

begin

	dbms_output.put_line(add_param(3,4));
	
end;

24. 定义一个函数: 获取给定部门的工资总和, 要求:部门号定义为参数, 工资总额定义为返回值.

create or replace function sum_sal(dept_id number)
       return number
       is
       
       cursor sal_cursor is select salary from employees where department_id = dept_id;
       v_sum_sal number(8) := 0;   
begin
       for c in sal_cursor loop
           v_sum_sal := v_sum_sal + c.salary;
       end loop;       

       --dbms_output.put_line('sum salary: ' || v_sum_sal);
       return v_sum_sal;
end;

执行函数

begin
    dbms_output.put_line(sum_sal(80));
end;

定义一个函数,获取给定部门的工资总和,要求部门号定义为参数,工资总和定义为返回值,返回总额肯定需要你把

一个人一个人的工资加起来,或者再准确点说,所有人都会把工资遍历一遍,使用游标吧,这就把刚才讲的给他结合起来了,

function get_sal,dept_id,number类型的,返回值类型,number的,is,需不需要声明一个变量,声明sum工资,是一个number

类型的,10,分号结束,然后begin,方法体怎么来写,我们现在这个时候再往下写,怎么求指定部门所有的和,使用一个游标,

游标是不是又得写在当时的declare里,那你这个就写这儿呗,指定这个人的部门的工资,cursor给他创建完以后,你就得open,

或者我用一个for更简单,让他加到这个里边,c.salary,这个你要先给他指定一个值,游标都不用关了,返回

create or replace function get_sal(dept_id number)

return number

is

	v_sumsal number(10) := 0;
	
	cursor salary_cursor is select salary from employees where department_id = dept_id;
	
begin

	for c in salary_cursor loop
	
		v_sumsal := v_sumsal + c.salary;
		
	end loop;
	
	return v_sumsal;
	
end;

get_sal,select,get_sal,80号部门的

select get_sal(80) from dual;

你要在这用declare也行,begin,dbms

declare

	v_deptid number(4) := 80;
	
begin

	dbms_output.put_line(get_sal(v_deptid));
	
end;

25. 关于 OUT 型的参数: 因为函数只能有一个返回值, PL/SQL 程序可以通过 OUT 型的参数实现有多个返回值

要求: 定义一个函数: 获取给定部门的工资总和 和 该部门的员工总数(定义为 OUT 类型的参数).
要求: 部门号定义为参数, 工资总额定义为返回值.

create or replace function sum_sal(dept_id number, total_count out number)
       return number
       is
       
       cursor sal_cursor is select salary from employees where department_id = dept_id;
       v_sum_sal number(8) := 0;   
begin
       total_count := 0;

       for c in sal_cursor loop
           v_sum_sal := v_sum_sal + c.salary;
           total_count := total_count + 1;
       end loop;       

       --dbms_output.put_line('sum salary: ' || v_sum_sal);
       return v_sum_sal;
end;   

执行函数:

delare 
  v_total number(3) := 0;

begin
    dbms_output.put_line(sum_sal(80, v_total));
    dbms_output.put_line(v_total);
end;

我们说函数,自变量可以有多个,但是函数返回值永远只有一个,这样才叫函数,这里为什么要定义一个out型的参数,

因为我们知道return永远是return一个,但是我又想存储过程当中,除了要返回工资总额之外,我还想让你返回点别的,

比如说这个,除了要你返回给定部门的工资总额之外,我还想看看这个部门有多少员工,那你这个一个函数,相当于两个

返回值,一个是指定部门的工资总和,一个是该部门的员工总数,你要是变成两个function,那变成一个里面怎么去做,

这个就要使用一个out型的参数,这个参数怎么用,我们就以他举例说一下,在这个里边也有一些说明,in默认不写的话

他就是in,比如in,标记表示传递给函数的值,在该函数执行过程中不改变,你像我们80号部门的80,就是你在执行的过程当中,

只要你用到这个变量了,他都是80,out标记表示一个值在函数中进行计算并通过该参数传递给调用语句,这个变量需要你在

函数执行之前,来定义一下,而这个值是可以被改变的,我们就写一个这个例子,定义一个函数,获取给定部门的工资总额,

和该部门的员工总数,把这个定义成一个out型的参数,部门号定义为参数,工资总额定义为返回值,那我们这个怎么写,定义一个函数,

给定部门的工资总额和他,除了把它当做一个参数之外,还得给一个总人数,total_count,也是一个number类型的,然后为了表明他

不是一个参数,你要这样写的话,那你调用这个函数,需要指定两个参数,不是一个参数,这个也是一个返回值,但是不是return出来的,

加一个out,get_sal1,这个number是工资总和,is,工资总和为0,然后呢,cursor还是指向他,需要指明total_count还是一个值,

一开始没有,所以他的值可以改变,赋值为0,这个是把它工资给累加起来,同时让他累加,还是返回工资总和,这个变量,就是在

你计算工资总和的过程当中,不知不觉的把这个值给他,记录了一下,那么这个值就相当于记录到了,然后给他end结束,执行完了,

create or replace function get_sal1(dept_id number,total_count out number)

return number

is

	v_sumsal number(10) := 0;
	
	cursor salary_cursor is select salary from employees where department_id = dept_id;
	
begin

	total_count := 0;
	
	for c in salary_cursor loop
	
		v_sumsal := v_sumsal + c.salary;
		
		total_count := total_count + 1;
		
	end loop;
	
	return v_sumsal;
	
end;

怎么用这个,多了一个,declare,我定义一个变量,number吧,我在这dbms,调用这个函数,前面是80号部门的,

我让他去记录,这个先给他赋一个值先,这个打印的结果就是你这个的返回值,80号部门的工资,但是他把我这个值

给记录下来了,那我这个时候打印我这个值先,这个是工资总和,这个是公司的人数

declare

	v_num number(5) := 0;
	
begin

	dbms_output.put_line(get_sal(80,v_sum));
	
	dbms_output.put_line(v_num);
	
end;

这个就是讲out变量怎么用,正常我们讲一个函数就一个返回值,这里同样也是一个,我就想在运算当中

再给我算一个值,其实相当于在看一个因变量,是直接让你返回的,然后被记录下来了,我可以通过这种方式,

让你在计算总工资的时候,把这个值给改变了,再后边就是存储过程,大家先把我讲的存储函数的给看一看,

过程没有返回值,刚才我们讲的都是存储函数,函数是有返回值的,你把这个格式给记住一下,这是函数的格式,

函数的格式有了,你再往里套,过程没有返回值了,这不叫function了,这个是面向过程

26*. 定义一个存储过程: 获取给定部门的工资总和(通过 out 参数), 要求:部门号和工资总额定义为参数

create or replace procedure sum_sal_procedure(dept_id number, v_sum_sal out number)
       is
       
       cursor sal_cursor is select salary from employees where department_id = dept_id;
begin
       v_sum_sal := 0;
       
       for c in sal_cursor loop
           --dbms_output.put_line(c.salary);
           v_sum_sal := v_sum_sal + c.salary;
       end loop;       

       dbms_output.put_line('sum salary: ' || v_sum_sal);
end;
[执行]
declare 
     v_sum_sal number(10) := 0;
begin
     sum_sal_procedure(80,v_sum_sal);
end;

获取给定部门的工资总和,然后部门号和工资总额定义为参数,那我写的时候把工资总额当成返回值了,是吧,他定义为参数,

对应的用存储过程写,没有返回值,所以你只能用out,用out来写,set serveroutput on

这是刚才写的存储函数,然后现在让你写一个存储过程,给定部门的工资总额,然后create or replace,

然后get_sal2,部门号这是作为一个参数,工资总额sumsal,out型的,也是number类型,没有return,is

就不用再定义了,sumsal赋个值,添加进去以后,for循环完了以后,sumsal,end结束

create or replace procedure get_sal2(dept_id number,sumsal out number)

is

	cursor salary_cursor is select salary from employees where department_id = dept_id;
	
begin

	sumsal := 0;
	
	for c in salary_cursor loop
	
		sumsal := sumsal + c.salary;
		
	end loop;
	
	dbms_output.put_line(sumsal);
	
end;

创建好以后调用一下,你不是要传一个变量吗,80号部门,你要写一个变量,那你还得在PL/SQL写,

declare,v_sal,number类型的,冒号等于,给一个初始化值,begin,80号部门的,把他放进去,end结束

declare

	v_sal number(10) := 0;
	
begin

	get_sal2(80,v_sal);
	
end;

因为他没有返回值了,就像我们JAVA里面的函数,这就打印80号部门的工资总和,这个就是一个存储过程,

你要是函数搞清楚了,存储过程,是比较简单的,把这个改一改,没有return,这里边也不要有return,一般里边都会

有一个输出语句,或者你也不一定是输出了,也有可能是增删改,因为增删改是不需要返回的,增删改不需要返回,

所以把增删改定义成一个存储过程

27*. 自定义一个存储过程完成以下操作: 
对给定部门(作为输入参数)的员工进行加薪操作, 若其到公司的时间在 (? , 95) 期间,    为其加薪 %5
                                                               [95 , 98)             %3       
                                                               [98, ?)               %1
得到以下返回结果: 为此次加薪公司每月需要额外付出多少成本(定义一个 OUT 型的输出参数).

create or replace procedure add_sal_procedure(dept_id number, temp out number)

is

       cursor sal_cursor is select employee_id id, hire_date hd, salary sal from employees where department_id = dept_id;
       a number(4, 2) := 0;
begin
       temp := 0;       

       for c in sal_cursor loop
           a := 0;    
       
           if c.hd < to_date('1995-1-1', 'yyyy-mm-dd') then
              a := 0.05;
           elsif c.hd < to_date('1998-1-1', 'yyyy-mm-dd') then
              a := 0.03;
           else
              a := 0.01;
           end if;
           
           temp := temp + c.sal * a;
           update employees set salary = salary * (1 + a) where employee_id = c.id;
       end loop;       
end;

对于给定部门,把它作为一个参数,相当于对指定部门进行操作,进行加薪,既然没有返回值,如果你需要一些返回的情况,

必须使用OUT来声明一下,他这里也确实需要,需要判断这个部门一个月额外付出多少成本,对每个人都加薪,额外输出多少钱,

create or replace,procedure,加薪,add_sal,使用这个,add_sal加薪,需要在里面给定部门,dept_id,number类型的,逗号,

他需要判断额外需要多少钱,这个作为一个out型的参数,他也是number类型的,没有return了,is,额外的要定义一个变量,

一个部门有很多人,就定义一个cursor,cursor,让他去遍历一下,cursor sal_cursor is select,你到底需要查什么,employees,

where department_id = dept_id,这都需要查什么,看你都需要什么,一般也是需要的,额外需要付出多少,一般employee_id也用,不对的

话再改,employee_id,salary,然后再加上hire_date,我先取这三个变量,从这三个表当中,这是加薪,这是加的一个东西,多定义一个变量,

一个是0.03,一个是0.01,比如我再定义一个变量,v_i吧,number类型的,两位小数,就是用来记录这个东西,差不多,然后直接begin,

用for,省得你open,fetch,close,循环,然后呢,判断一下hire_date,不同的hire_date所赋的值是不一样的,如果c的hire_date是在这个

时间段的,这个怎么写啊,让这个hire_date小于一个时间,字符串和date的一个转换,那我就这样一下吧,to_char,是一个date型的,

如果这个是小于1995,按说字符串是不可以比大小的,但是如果你字符串是纯数字的话,他有一个隐式转换,隐式转换纯数字,纯数字的

字符串可以隐式转换,如果是这样的话,then,为其加百分之五,v_i记录一下,加薪的幅度,elsif,1998,0.03,其余的else,直接then了,

然后if就是end if,end if完了,还是得更新一下他的工资,下面操作,1更新工资,2付出的成本,先看这个,一开始他的成本在这儿呢,

在这给他赋值,temp冒号等于0,付出的成本,temp = temp + c.salary*v_i,这就是额外多的,更新工资,update,update employees,

set salary = salary(1+v_i),where employee_id = c.employee_id,然后给他这样操作了,操作完以后,end loop,end

create or replace procedure add_sal(dept_id number,temp_sal out number)

is

	cursor sal_cursor is select employee_id,salary,hire_date from employees where department_id = dept_id;
	
	v_i number(4,2) := 0;
	
begin

	temp_sal := 0;
	
	for c in sal_cursor loop
	
		if to_char(c.hire_date,'yyyy') < '1995' then v_i := 0.05;
		
		elsif to_char(c.hire_date,'yyyy') < '1998' then v_i := 0.03;
		
		else v_i := 0.01;
		
		end if;
		
		update employees set salary = salary*(1+v_i) where employee_id = c.employee_id;
		
		temp_sal := temp_sal + c.salary*v_i;
		
	end loop;
	
end;

创建好以后,然后呢,执行,这里你定义一个变量,declare定义一个变量,定义一下到底要花多少钱,

number,10个单位,冒号等于0,begin,add_sal,80号部门的,然后呢v_temp,我把你要花的给你输出一下

create or replace procedure add_sal(dept_id number,temp_sal out number)

is

	cursor sal_cursor is select employee_id,salary,hire_date from employees where department_id = dept_id;
	
	v_i number(4,2) := 0;
	
begin

	temp_sal := 0;
	
	for c in sal_cursor loop
	
		if to_char(c.hire_date,'yyyy') < '1995' then v_i := 0.05;
		
		elsif to_char(c.hire_date,'yyyy') < '1998' then v_i := 0.03;
		
		else v_i := 0.01;
		
		end if;
		
		update employees set salary = salary*(1+v_i) where employee_id = c.employee_id;
		
		temp sal := temp_sal + c.salary*v_i;
		
	end loop;
	
	dbms_output.put_line(temp_sal);
	
end;

declare

	v_temp number(10) := 10;
	
begin

	add_sal(80,_v_temp);
	
end;

这就叫存储过程,我觉得存储过程比存储函数要简单,你把存储函数理解理解,这个改一改就了事了,

这就是存储过程,存储过程就搞定了

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值