文章详情

短信预约信息系统项目管理师 报名、考试、查分时间动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

什么是 PL/SQL? 怎么用?

2016-03-08 14:34

关注

什么是 PL/SQL? 怎么用?

1.什么是PL/SQL?

PL/SQLProcedure Language/SQL)是Oraclesql语言的过程化扩展,指在SQL命令语言中增加了过程处理语句(如分支/条件、循环变量、类型等),使SQL语言具有过程处理能力。把SQL语言的数据操纵能力与过程语言的数据处理能力结合起来,使得PLSQL面向过程但比过程语言简单、高效、灵活和实用。

 

基本语法结构

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

 

 

2.变量

-- 声明变量的语法:
变量名 类型(长度);
i varchar2(20);


--变量赋值的语法
变量名 :=变量值
i :="煌煌"

 

举例使用:

--入门练习1;打印"welcome!!"
begin 
  dbms_output.put_line("welcome!!!");
  end;



--实例1;定义变量 i,并赋值 "你好",输出
--变量类型,一定要支持赋值的长度
declare 
 i varchar2(20);
begin 
   i :="你好";
   dbms_output.put_line("输出内容是:" || i);
end;   




--多个变量
declare
 sname varchar2(20):="huangsir";
 age int:=18;
 sex varchar2(20):="男";
 begin 
   dbms_output.put_line("姓名:" ||sname || ",年龄:" ||age || ",性别:" ||sex);
 end;

 

如何执行查看呢?

 

 

Select into方式 赋值

语法结构: into关键字是能用在过程中

select 列名1,列名2  into  变量名1,变量名2  from 表名 where 条件

举例:

--练习1;打印业主名称
declare 
  --声明变量,用于存放name的值
  v_name varchar2(50);

begin
  --执行查询语句,获得name的值,并赋值变量
  select  name into v_name from t_owners where id=11;
  --打印变量
dbms_output.put_line(v_name);
end;

 

3. 变量类型 %type

如果自定义类型大小,如果设置的太小会出现数字或值错误:字符缓存区太小的错误
所以可用%type自己引用表类型即可

语法:

-- 语法
变量名  表名.列名%type;
-- 实例
v_name towners.name%type;

 

案例:

--练习2;打印业主名称
declare 
  --声明变量,用于存放name的值
  v_name t_owners.name%type;    --使用%type  可以不用自定义数据类型,直接从表数据获取类型

begin
  --执行查询语句,获得name的值,并赋值变量
  select  name into v_name from t_owners where id=11;
  --打印变量
dbms_output.put_line(v_name);
end;

 

练习:

--练习3:  需求:计算台账表中编号为1的用户当月用水金额。
      --要求输出:单价、吨数、金额、上月用水量、本月用水量

declare
 v_price number; --单价
 v_num0 number;   --t_account.num0%type   上月累计用水量
 v_num1 number;   --t_account.num1%type   本月累计用水量
 v_usenum number;  --t_account.usenum%type    使用量
 v_money number;  --金额
 v_usenum2 number;  --吨数
 
begin
  v_price:=3.45; --单价赋值
  --查询数据;获得用水量,金额
 select num0,num1,usenum,money into v_num0,v_num1,v_usenum,v_money from t_account where id = 45;
    --吨数 19920 /1000 ->> 19.920 -->19.92
    v_usenum2:=round(v_usenum/1000 ,2);
       v_money:=v_price*v_usenum2;
   --打印
   dbms_output.put_line("单价、"|| v_price ||"吨数、"||v_usenum2|| "金额"||v_money ||"、上月用水量"||v_num0 ||"、本月用水量"||v_num1); 
    
end;

 

 

%ROWTYPE   记录型 

声明变量 :

--语法
变量 表名%rowtype;
--实例
v_account t_account%rowtype;

 

赋值 :

-- 单列
select 列名,列名2,... into 变量.列名,变量.列名2,...  from 表名;
-- 所有
select * into 变量  from 表名;

 

示例:重写上个练习:使用%rowtype

declare 
 --单价
  v_price number;
  --声明行变量
  v_account t_account%rowtype;
begin 
   --单价赋值
   v_price :=3.45;
   --保存-行数
   select * into v_account from t_account where id=45;
   --打印
   dbms_output.put_line("单价"||v_price ||",金额"||v_account.money ||",上月用水量"
   ||v_account.num0 ||",本月用水量"||v_account.num1);
   end;

 

 

4. 异常

在运行程序时出现的错误叫做异常

发生异常后,语句将停止执行,控制权转移到 PL/SQL 块的异常处理部分

异常有两种类型:

 

预定义异常

Oracle预定义异常 21个

命名的系统异常

产生原因

ACCESS_INTO_NULL

未定义对象

CASE_NOT_FOUND

CASE 中若未包含相应的 WHEN ,并且没有设置 ELSE 时

COLLECTION_IS_NULL

集合元素未初始化

CURSER_ALREADY_OPEN

游标已经打开

DUP_VAL_ON_INDEX

唯一索引对应的列上有重复的值

INVALID_CURSOR

在不合法的游标上进行操作

INVALID_NUMBER

内嵌的 SQL 语句不能将字符转换为数字

NO_DATA_FOUND

使用 select into 未返回行

TOO_MANY_ROWS

执行 select into 时,结果集超过一行

ZERO_DIVIDE

除数为 0

SUBSCRIPT_BEYOND_COUNT

元素下标超过嵌套表或 VARRAY 的最大值

SUBSCRIPT_OUTSIDE_LIMIT

使用嵌套表或 VARRAY 时,将下标指定为负数

VALUE_ERROR

赋值时,变量长度不足以容纳实际数据

LOGIN_DENIED

PL/SQL 应用程序连接到 oracle 数据库时,提供了不正确的用户名或密码

NOT_LOGGED_ON

PL/SQL 应用程序在没有连接 oralce 数据库的情况下访问数据

PROGRAM_ERROR

PL/SQL 内部问题,可能需要重装数据字典& pl./SQL 系统包

ROWTYPE_MISMATCH

宿主游标变量与 PL/SQL 游标变量的返回类型不兼容

SELF_IS_NULL

使用对象类型时,在 null 对象上调用对象方法

STORAGE_ERROR

运行 PL/SQL 时,超出内存空间

SYS_INVALID_ID

无效的 ROWID 字符串

TIMEOUT_ON_RESOURCE

Oracle 在等待资源时超时

 

 

语法:

-- 语法
declare
begin
	-- 正常代码
	-- 异常块
	exception
		when 异常类型 then
			处理
		when 异常类型 then
			处理
		....
end;
-- 常见异常类型:
no_date_found , 没有数据异常,查询结果为null
too_many_rows,太多行,查询结果大于1条

 

练习4:查询台账表,id为1所有信息,并打印部分 -- 异常情况--没有数据

-- 异常处理
-- 练习4:查询台账表,id为1所有信息,并打印部分
declare 
  v_account t_account%rowtype;
begin 
  --查询
  select * into v_account from t_account where id = 999;
  --打印
  dbms_output.put_line("上月用水量" || v_account.num0 || "本月用水量" || v_account.num1);
  -- 异常处理
  exception 
    when no_data_found then
      dbms_output.put_line("没有查询到数据");
    when too_many_rows then
      dbms_output.put_line("查询结果大于1条");
end;

 

练习4:查询台账表,id为1所有信息,并打印部分 -- 异常情况--查询多条数据

declare 
  v_account t_account%rowtype;
begin 
  --查询
  select * into v_account from t_account ; --少了where id=45 ,数据有多条
  --打印
  dbms_output.put_line("上月用水量" || v_account.num0 || "本月用水量" || v_account.num1);
  -- 异常处理
  exception 
    when no_data_found then
      dbms_output.put_line("没有查询到数据");
    when too_many_rows then
      dbms_output.put_line("查询结果大于1条");
end;

 

 

5. 条件判断

基本语法1

if 条件 then

     业务逻辑

end if;

 

基本语法2

 if 条件 then

   业务逻辑

 else

   业务逻辑

 end if;

 

基本语法3

if 条件 then
     业务逻辑
elsif 条件 then
     业务逻辑
else
     业务逻辑  
end if;

 

实例:需求:设置三个等级的水费 5吨以下2.45元/吨 5吨到10吨部分3.45元/吨 ,超过10吨部分4.45 ,根据使用水费的量来计算阶梯水费

declare 
   --定义3个水费价格
   v_price1 number;
    v_price2 number;
    v_price3 number;
   --查询台账记录
   v_account t_account%rowtype;
   --使用量(吨数)
   v_usenum2 number;
   --金额
   v_money number;
begin
    --确定水费价格
    v_price1:=2.45;
     v_price2:=3.45;
      v_price3:=4.45;
    --查询记录
    select  * into v_account from t_account where id=45;
    --计算使用量
     v_usenum2:=round(v_account.usenum/1000,2);
     
    
    --根据使用量,计算阶梯水费
    
    if v_usenum2<=5 then
    --小于5吨 ,  使用量*2.45
     v_money:=v_usenum2*2.45;
     elsif v_usenum2 <=10 then
    --小于10吨   5* 2.45 +(使用量-5) *3.45
      v_money:=5 *2.45 +(v_usenum2-5)*3.45;
    else
    --大于10吨   5*2.45 +5*3.45 +使用量-10) *4.45
    v_money:=5 *2.45+5*3.45+(v_usenum2-10)*4.45;
    end if;
    --打印水费
    dbms_output.put_line(v_money);
end;

 

 

6.循环

(1)无条件循环

语法:

--语法
loop
	-- 代码
	-- 结束循环
	exit;
end loop;

 

练习:输出从1开始的100个数

declare
 v_i int :=1;
begin
  loop
    dbms_output.put_line(v_i);
    --累加
    v_i:=v_i+1;
    -- 退出
   if v_i > 100 then
     exit;
     end if;
     end loop;
end;

 

 

(2)条件循环-while

语法:

--语法结构
while 条件
loop
  ...
end loop;

 

举例:求1-100和,并打印

declare
--计数器
 v_i int :=1;
 --求和变量
 v_sum int :=0;
begin 
  while v_i <=100
  loop
     --求和
     v_sum :=v_sum+v_i;
     
     --累加
     v_i:=v_i +1;
     end loop;
     --打印
     dbms_output.put_line(v_sum);
end;     

 

 

(3)for循环

语法:

for 变量  in 起始值..终止值
loop
  
end loop;

 

举例:

求1-100所有偶数的和,并打印

declare
--计数变量
v_i int;
 --求和变量
 v_sum int :=0;
begin
  for v_i in 1..100
    loop
      --mod()用于求余
     if  mod(v_i,2)= 0 then
      v_sum :=v_sum+v_i;
      end if;
    end loop;  
      dbms_output.put_line(v_sum); 
end;

 

 

 

练习前.需要知道的小知识:

declare
begin
  --一行输出
    dbms_output.put("123");
  --换行输出
  dbms_output.put_line("abc");

end;

 

练习: 99乘法表 :分步骤实现

--1.普通循环
declare 
 vi int;
begin
  --循环
  for vi in 1..9
    loop
      dbms_output.put_line(vi);
      end loop;
end;




--2.嵌套循环
declare 
 vi int;
 vj int;
begin 
  --嵌套循环
  for vi in 1..9
    loop
      --内部循环
     for vj in 1..9
       loop 
           dbms_output.put_line(vi || vj);
       end loop;
    
     end loop; 
end;      




---3.总

declare 
 v_i int;
 v_j int;
begin
  --嵌套循环
  for v_i in 1..9
    loop
      --内部循环
      for v_j in 1..v_i
        loop 
          dbms_output.put(v_j || "*" || v_i ||"=" ||(v_i*v_j) );
      dbms_output.put("   "); 
     end loop;
     dbms_output.put_line("");
     end loop;
end;

 

 

7.游标

(1)什么是游标?

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

 

 

语法

--在声明区声明游标,语法如下:
cursor 游标名称 is SQL语句;

 

 

declare
    --声明游标
    cursor 游标名称 is 查询语句;
begin
    open 游标名称;
    loop;
        -- 给游标指向当前行进行命名,方便获得当前行的数据
        fetch 游标名称 into 变量;
        -- 使用当前行数据
        -- 结束信息
        exit when 游标名称%notfound;
    end loop;
    close 游标名称;
end;

 

 

案例: 需求:打印业主类型为1的价格表 

实现方式1:

--方式1;游标的基本操作
declare
  --声明游标
  cursor cur_pricetable is select * from t_pricetable where ownertypeid=1;
 --声明表里,可以存放一条记录
 v_pricetable t_pricetable%rowtype;

begin
   --开启
   open cur_pricetable;
     
   loop 
     --游标指向行数据,打印价格(给游标中的数据进行命名,方便获得行数据)
     fetch cur_pricetable into v_pricetable;
    
     --没有数据,退出
  exit when cur_pricetable%notfound;
  --打印
   dbms_output.put_line(v_pricetable.price);
 end loop;
   
   --关闭
   close cur_pricetable;
end;

 

 

实现方式2.for循环(简化)

declare
 --声明游标
 cursor cp is select * from t_pricetable where ownertypeid=1;
  --变量
  vp t_pricetable%rowtype;
begin
    --for遍历
     for vp in cp
       loop
         dbms_output.put_line(vp.price);
       end loop;  
end;

 

 

具有参数的游标

语法:

 --curso 游标名称(参数名称 类型) is  SQL语句..where id=参数名称;
 -- 在for vp in cp(想要传递的参数);

 

案例:

declare
 --声明游标
 cursor cp(v_ownertypeid number) is select * from t_pricetable where ownertypeid=v_ownertypeid;
  --变量
  vp t_pricetable%rowtype;
begin
    --for遍历
     for vp in cp(3)
       loop
         dbms_output.put_line(vp.price);
       end loop;  
end;

 

 

 

 

看完恭喜你,又知道了一点点!!!

你知道的越多,不知道的越多! 

~感谢志同道合的你阅读,  你的支持是我学习的最大动力 ! 加油 ,陌生人一起努力,共勉!!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯