2023-05-19 21:02

从plsql到存储过程

徐福沛

数据库

(678)

(0)

收藏

blog

从plsql到存储过程

    基本语法结构

declare
	-- 声明变量
begin
	-- 代码逻辑
exception
	--异常处理
end;

    变量

声明变量的语法

变量名 类型(长度);

变量赋值的语法

变量:=变量值


例子:

-- 变量声明与赋值
declare 
  v_price number(10,2);   -- 单价
  v_usenum number;         -- 水费字数
  v_usenum2 number(10,2); -- 吨数
  v_money number(10,2);   --金额
  
begin
  v_price := 2.45; -- 单价赋值
  v_usenum := 9213; --水费的字数
  v_usenum2 := round(v_usenum/1000,2); -- 吨数
  v_money := v_price*v_usenum2; -- 金额
  
  dbms_output.put_line('金额:'||V_money);
  
end;

	-- 输出结果:金额:22.56
**************************************************************************
-- 变量 是数据库中查出来的数据
-- select 列名 into 变量名 
declare 
  v_price number(10,2);   -- 单价
  v_usenum number;         -- 水费字数
  v_usenum2 number(10,2); -- 吨数
  v_money number(10,2);   --金额
  v_num0 number; -- 上月水表数
  v_num1 number; -- 本月水表数
  
  
begin
  v_price := 2.45; -- 单价赋值
  -- v_usenum := 9213; --水费的字数
  --从数据库读取
  select usenum,num0,num1 into v_usenum,v_num0,v_num1 from t_account where year = '2012' and month = '01' and owneruuid = 1;
  
  v_usenum2 := round(v_usenum/1000,2); -- 吨数
  v_money := v_price*v_usenum2; -- 金额
  
  dbms_output.put_line('水费字数:'||v_usenum||' 金额:'||v_money||' num0:'||v_num0||' num1:'||v_num1);
  
end;
	-- 输出结果:水费字数:2104 金额:5.15 num0:15 num1:20

    属性类型

-- 属性类型 (引用类型 表名.列名%type)
declare 
  v_price number(10,2);   -- 单价
  v_usenum t_account.usenum%type;         -- 水费字数
  v_usenum2 number(10,2); -- 吨数
  v_money number(10,2);   --金额
  v_num0 t_account.num0%type; -- 上月水表数
  v_num1 t_account.num1%type; -- 本月水表数
begin
  v_price := 2.45; -- 单价赋值
  -- v_usenum := 9213; --水费的字数
  select usenum,num0,num1 into v_usenum,v_num0,v_num1 from t_account where year = '2012' and month = '01' and owneruuid = 1;
  
  v_usenum2 := round(v_usenum/1000,2); -- 吨数
  v_money := v_price*v_usenum2; -- 金额
  
  dbms_output.put_line('水费字数:'||v_usenum||' 金额:'||v_money||' num0:'||v_num0||' num1:'||v_num1);
end;

-------------------------------------------------------

--属性类型 (行记录型 表名%rowtype)
declare 
  v_price number(10,2);   -- 单价
  v_usenum2 number(10,2); -- 吨数
  v_money number(10,2);   --金额
  v_account t_account%rowtype; -- 台账行记录类型
-- 相当于java中的实体类 直接通过 表名.列名 调用
begin
  v_price := 2.45; -- 单价赋值
  -- v_usenum := 9213; --水费的字数
  select * into v_account from t_account 
  where year = '2012' and month = '01' and owneruuid = 1;
  
  v_usenum2 := round(v_account.usenum/1000,2); -- 吨数
  v_money := v_price*v_usenum2; -- 金额
  
  dbms_output.put_line('水费字数:'||v_account.usenum||' 金额:'||v_money||' num0:'||v_account.num0||' num1:'||v_account.num1);
end;


    异常(例外)

有 预定义异常和用户自定义异常

--语法结构
exception 
	when 异常类型 then 
		异常处理
		
-- no_data_found
declare 
  v_price number(10,2);   -- 单价
  v_usenum2 number(10,2); -- 吨数
  v_money number(10,2);   --金额
  v_account t_account%rowtype; -- 台账行记录类型
begin
  v_price := 2.45; -- 单价赋值
  -- v_usenum := 9213; --水费的字数
  select * into v_account from t_account 
  where year = '2012' and month = '01' and owneruuid = 100;
  
  v_usenum2 := round(v_account.usenum/1000,2); -- 吨数
  v_money := v_price*v_usenum2; -- 金额
  
  dbms_output.put_line('水费字数:'||v_account.usenum||' 金额:'||v_money||' num0:'||v_account.num0||' num1:'||v_account.num1);

exception 
  when no_data_found then 
    dbms_output.put_line('没有找到数据');
end;

--too_many_rows
declare 
  v_price number(10,2);   -- 单价
  v_usenum2 number(10,2); -- 吨数
  v_money number(10,2);   --金额
  v_account t_account%rowtype; -- 台账行记录类型
begin
  v_price := 2.45; -- 单价赋值
  -- v_usenum := 9213; --水费的字数
  select * into v_account from t_account 
  where year = '2012' and month = '01';
  
  v_usenum2 := round(v_account.usenum/1000,2); -- 吨数
  v_money := v_price*v_usenum2; -- 金额
  
  dbms_output.put_line('水费字数:'||v_account.usenum||' 金额:'||v_money||' num0:'||v_account.num0||' num1:'||v_account.num1);
exception 
  when no_data_found then 
    dbms_output.put_line('没有找到数据');
  when too_many_rows then 
    dbms_output.put_line('返回多行数据');
end;

    条件判断

--基本语法
if 条件 then 
	业务逻辑
end if;
--相当于
if(){

}

------------------------------------

if 条件 then 
	业务逻辑
else
	业务逻辑
end if;
--相当于
if(){

}else{

}

------------------------------------
if 条件 then
	业务逻辑
elsif then
elsif then
else
end if;
-- 相当于
if(){

}else if(){

}else{

}

------------------------------------------------

declare 
  v_price1 number(10,2);   -- 单价
  v_price2 number(10,2);   -- 单价
  v_price3 number(10,2);   -- 单价
    
  v_usenum2 number(10,2); -- 吨数
  v_money number(10,2);   --金额
  v_account t_account%rowtype; -- 台账行记录类型
begin
  v_price1 := 2.45; -- 单价赋值(五吨以下)
  v_price2 := 3.45; -- 单价赋值(五到十吨)
  v_price3 := 4.45; -- 单价赋值(十吨以上)
           
  select * into v_account from t_account 
  where year = '2012' and month = '01' and owneruuid = 1;
  
  v_usenum2 := round(v_account.usenum/1000,2); -- 吨数
  --v_money := v_price*v_usenum2; -- 金额
  
  --阶梯水费计算
  if v_usenum2<=5 then 
    v_money := v_price1*v_usenum2;
  elsif v_usenum2>5 and v_usenum2<=10 then
    v_money := v_price1*5+v_price2*(v_usenum2-5);
  else
    v_money := v_price1*5+v_price2*5+v_price3*(v_usenum2-10);
  end if;
  
  dbms_output.put_line('水费字数:'||v_account.usenum||' 金额:'||v_money||' num0:'||v_account.num0||' num1:'||v_account.num1);

exception 
  when no_data_found then 
    dbms_output.put_line('没有找到数据');
  when too_many_rows then 
    dbms_output.put_line('返回多行数据');
end;

循环

    无条件循环

--基本语法
loop 
	--循环语句
end loop;
----------------------------------------------------------
--无条件循环:1到100
declare 
    v_num number;
begin
  v_num := 1;
  loop 
    dbms_output.put_line(v_num);
    v_num := v_num+1;
    
    if v_num>100 then
      exit; -- loop (无条件循环)中需要写exit跳出循环 相当于java中的return
     end if;
     -- exit when v_num>100; -- 也可以不写if then 直接写这个 这种写法效果是一样的
  end loop;
end;

    条件循环

--基本语法 
while 条件
loop 
	--循环语句
end loop;

-----------------------------------------------------------
--有条件循环:1到100
declare
  v_num number;
begin
  v_num := 1;

  while v_num<=100
  loop
    dbms_output.put_line(v_num);
    v_num:=v_num+1;
      
  end loop;

end;
-----------------------------------------------------------

declare
  v_num number;
begin
  v_num := 1;

  while v_num<=100
  loop
    dbms_output.put_line(v_num);
    v_num:=v_num+1;
    
  exit when v_num>50 -- 可以手动跳出
  
  end loop;

end;

    for循环

--基本语法
declare -- declare可以不写
begin
  for 变量 in 1..100 --变量可以不声明 但是这个变量只能在循环着中使用
  loop
 	
  end loop;
end;


游标

游标是系统为用户开设的一个数据缓冲区,存放sql语句的执行结果。我们可以把游标理解PL/SQL中的结果集。

    基本语法

--在声明区声明游标
cursor 游标名称 is sql语句

--使用游标语法
open 游标名称 --打开游标
loop
	fetch 游标名称 into 变量
	exit when 游标名称%notfound -- notfound 是游标中的属性 当游标走到底会返回一个true 除此之外还有一个found的属性它返回的值与notfound相反
end loop;
close 游标名称;--关闭游标

    不带参数的游标

declare
  cursor cur_pricetable is select * from t_account where usenum = '2104';--声明游标
  v_pricetable t_account%rowtype; 
  
begin
  open cur_pricetable;--打开游标
       loop 
         fetch cur_pricetable into  v_pricetable;--提取游标
         
         exit when cur_pricetable%notfound;--退出循环
         
         dbms_output.put_line('ID:'||v_pricetable.OWNERUUID);
         
       end loop;
  
  close cur_pricetable;--关闭游标
  
end;


    带参数的游标

declare
  cursor cur_pricetable(v_ownertype varchar2) is select * from t_account where usenum = v_ownertype;
  v_pricetable t_account%rowtype;
  
begin
  open cur_pricetable('2104');--打开游标 感觉这个open相当于java里调用方法传参数
       loop 
         fetch cur_pricetable into  v_pricetable;--提取游标
         
         exit when cur_pricetable%notfound;--退出循环
         
         dbms_output.put_line('ID:'||v_pricetable.OWNERUUID);
         
       end loop;
  
  close cur_pricetable;--关闭游标
  
end;

    for循环  游标

declare
  cursor cur_pricetable(v_ownertype varchar2) is select * from t_account where usenum = v_ownertype;
  -- v_pricetable t_account%rowtype; --自动声明 但是只能在循环中使用
  
begin
  for v_pricetable in cur_pricetable('2104') --带参数的
  -- for v_pricetable in cur_pricetable --如果不带参数不写就行了
    loop 
         dbms_output.put_line('ID:'||v_pricetable.OWNERUUID);
    end loop;
end;
--for循环会自动打开关闭游标 会自动提取游标 变量也会自动声明


存储函数

存储函数又称为自定义函数。可以接收一个或多个参数,返回一个结果。在函数中我们可以使用plsql进行逻辑处理。

    存储函数基本语法

create [or replace] function 函数名称
(参数名称 参数类型,参数名称 参数类型,....)
return 结果变量数据类型
is
	变量声明部分;
begin
	逻辑部分;
	return 结果变量;
[exception
    异常处理部分]
end;
create or replace function fn_gecaddress
(v_id number)
return varchar2
is
  v_name varchar2(30);
begin 
  select year into v_name from t_account where OWNERUUID = v_id;
  return v_name;
end; -- 执行之后在function文件夹中可以看到
-------------------------------------------------------------------------
--自定义存储函数测试
select fn_gecaddress(1) from dual;--通过函数名调用 有参数需要传参

存储过程

    存储过程是被命名的pl/ql块,存储于数据库中,是数据库对象的一种,应用程序可以调用存储过程,执行相应的逻辑。

    存储过程与存储函数都可以封装一定的业务逻辑并返回结果,存在区别如下:

  1. 存储函数中有返回值,且必须返回;而存储过程没有返回值,可以通过传出参数返回多个值。

  2. 存储函数可以在select语句中直接使用,而存储过程不能。过程多数是被应用程序所调用。

  3. 存储函数一般都是封装一个查询结果,而存储过程一般都橙装一段事务代码。

    存储过程基本语法

create [or replace] procedure 存储过程名称
(参数名 类型,参数名 类型,参数名 类型)
is|as
	变量声明;
begin
	逻辑部分
[exception
	异常处理部分]
end;

参数只指定类型,不指定长度

过程参数的三种模式:

IN 传入参数(默认,可以不写)

OUT 传出参数,主要用于返回程序运行结果

IN OUT 传入传出参数


    不带传出参数的存储过程

CREATE OR REPLACE procedure pro_owners_add
(
v_id number,
v_usenum number,
v_year varchar2,
v_month varchar2
)
is

begin

  insert into t_account values(v_id,v_usenum,v_year,v_month,0,0);
  commit;

end;
--调用存储过程
call pro_owners_add(11,22,'ss','kk')
--或者
begin
    pro_owners_add(66,77,'qs','dk');
end;


    带传出参数的存储过程

CREATE OR REPLACE procedure pro_owners_add
(
v_id number,
v_usenum number,
v_year varchar2,
v_month varchar2,
v_kk out number
)
is

begin
  v_kk:=v_id;
  insert into t_account values(v_id,v_usenum,v_year,v_month,0,0);
  commit;

end;

--调用
declare
  v_id number;
begin
  pro_owners_add(65,65,'qgs','dgk',v_id);
  dbms_output.put_line(v_id);
end;


0条评论

点击登录参与评论