作者:IT邦德
中国DBA联盟(ACDU)成员,目前从事DBA及程序编程
(Web\java\Python)工作,主要服务于生产制造
现拥有 Oracle 11g  OCP/OCM、
Mysql、Oceanbase(OBCA)认证
分布式TBase\TDSQL数据库、国产达梦数据库以及红帽子认证
从业8年DBA工作,在数据库领域有丰富的经验
B站主播Oracle、Mysql、PG实战课程,请搜索:jeames007

擅长Oracle数据库运维开发,备份恢复,安装迁移,性能优化、故障应急处理等。

在这里插入图片描述

前言

本文总结了PL\SQL存储过程及包的使用,大家多点赞关注!

1.pl/sql块介绍

1.1、只包括执行部分的pl/sql块
SQL>set serveroutput on --打开输出选项   
begin    /*执行部分——要执行的pl/sql语句和sql语句*/
dbms_output.put_line('hello');   
end;  
/
/*dbms_output是oracle所提供的包(类似java的开发包),该包包含一些过程,put_line就是dbms_output包的一个过程*/
包含定义部分和执行部分的pl/sql块
1.2、包含定义部分和执行部分的pl/sql块
SQL>declare  
v_ename varchar2(5); --定义字符串变量   
begin  
select ename into v_ename from emp where empno=&aa;   
dbms_output.put_line('雇员名:'||v_ename);   
end;   
/  
1.3、	包含定义部分,执行部分和例外处理部分的pl/sql块
SQL>declare  
--定义变量   
v_ename varchar2(5);   
v_sal  number(7,2);   
begin  
--执行部分   
select ename,sal into v_ename,v_sal from emp where empno=&aa;   
--在控制台显示用户名   
dbms_output.put_line('用户名是:'||v_ename||' 工资:'||v_sal);   
--异常处理   
exception   
when no_data_found then  
dbms_output.put_line('朋友,你的编号输入有误!');   
end;   
/  

2.pl/sql分类

2.1、过程
SQL>create procedure sp_pro(spName varchar2, newSal number) is 
begin 
--执行部分,根据用户名去修改工资
update emp set sal=newSal where ename=spName;
end;
/ 
SQL>exec sp_pro1('SCOTT',4556);   --调用
2.2、函数
--输入雇员的姓名,返回该雇员的年薪  
SQL>create function annual_incomec(name varchar2)   
return number is  
annual_salazy number(7,2);   
begin  
--执行部分   
select sal*12+nvl(comm, 0) into annual_salazy from emp where ename=name;   
return annual_salazy;   
end;   
/  
--在sqlplus中调用函数 
SQL>var income number
call annual_incomec('SCOTT') into: income;
print income
2.3、	包
--包用于在逻辑上组合过程和函数,它由包规范和包体两部分组成。 
实例1: 
--创建一个包sp_package 
--声明该包有一个过程update_sal 
--声明该包有一个函数annual_income 
SQL>create package sp_package is  
procedure update_sal(name varchar2, newsal number);   
function annual_income(name varchar2) return number;   
end;  
/
实例2:
--给包sp_package实现包体 
SQL>create or replace package body sp_package is  
procedure update_sal(name varchar2, newsal number)    
is  
begin    
update emp set sal = newsal where ename = name;   
end;   
function annual_income(name varchar2) return number is  
annual_salary number;   
begin  
select sal * 12 + nvl(comm, 0) into annual_salary from emp   
where ename = name;   
return annual_salary;   
end;   
end;   
/  
如何调用包的过程或是函数 
SQL> call sp_package.update_sal('SCOTT', 1500);
2.4、触发器
常用的触发事件包括insert,update,delete语句,而触发操作实际就是一个pl/sql块。可以使用create trigger来建立触发器。 

3.定义并使用变量,复合类型

3.1、标量定义的案例
定义一个变长字符串 
v_ename varchar2(10); 
定义一个小数,范围 -9999.99~9999.99 
v_sal number(6,2); 
定义一个小数并给一个初始值为5.4 :=是pl/sql的赋值号 
v_sal2 number(6,2):=5.4; 
定义一个日期类型的数据
v_hiredate date; 
定义一个布尔变量,不能为空,初始值为false 
v_valid boolean not null default false; 
案例1:
SQL> declare  
c_tax_rate number(3,2):=0.03;   
--用户名   
v_ename varchar2(5);   
v_sal number(7,2);   
v_tax_sal number(7,2);   
begin  
--执行   
select ename,sal into v_ename,v_sal from emp where empno=&no;   
--计算所得税   
 v_tax_sal := v_sal*c_tax_rate;   
--输出   
dbms_output.put_line('姓名是:'||v_ename||'工资:'||v_sal||' 交税:'||v_tax_sal);   
end;   
/  
输出的结果是:
姓名是:SCOTT工资:2900 交税:87
PL/SQL procedure successfully completed
案例2:
标量(scalar)——使用%type类型
比如上例的v_ename,这样定义: v_ename emp.ename%type; 
3.2、复合变量(composite)
用于存放多个值的变量。主要包括这几种: 
	pl/sql记录 
	pl/sql表 
	嵌套表
	varray 
3.2.1、pl/sql记录
类似于高级语言中的结构体,需要注意的是,当引用pl/sql记录成员时,必须要加记录变量作为前缀(记录变量.记录成员)如下:
SQL>declare  
--定义一个pl/sql记录类型emp_record_type,类型包含3个数据name,salary,title。说白了,就是一个类型可以存放3个数据,主要是为了好管理   
type emp_record_type is record(   
name   emp.ename%type,   
salary emp.sal%type,   
title  emp.job%type);   
--定义了一个sp_record变量,这个变量的类型是emp_record_type   
sp_record emp_record_type;   
begin  
select ename, sal, job into sp_record from emp where empno = 7788;   
dbms_output.put_line ('员工名:' || sp_record.name);   
end;  
/
3.2.2、pl/sql表
相当于高级语言中的数组,但是需要注意的是在高级语言中数组的下标不能为负数,而pl/sql是可以为负数的,并且表元素的下标没有限制。实例如下: 
SQL>declare  
--定义了一个pl/sql表类型sp_table_type,该类型是用于存放emp.ename%type   
--index by binary_integer 表示下标是整数   
type sp_table_type is table of emp.ename%type    
index by binary_integer;   
--定义了一个sp_table变量,这个变量的类型是sp_table_type   
sp_table sp_table_type;   
begin  
select ename into sp_table(-1) from emp where empno = 7788;   
dbms_output.put_line('员工名:' || sp_table(-1));   
end;  
/
说明: 

sp_table_type 是pl/sql表类型 
emp.ename%type 指定了表的元素的类型和长度 
sp_table 为pl/sql表变量 
sp_table(0) 则表示下标为0的元素 
注意:如果把select ename into sp_table(-1) from emp where empno = 7788;变成select ename into sp_table(-1) from emp;则运行时会出现错误,错误如下: 
ORA-01422:实际返回的行数超出请求的行数 
解决方法是:使用参照变量

如果觉得文章对你有帮助,点赞、收藏、关注、评论,一键四连支持
您的批评指正是我写作的最大动力!

❤️ 技术交流可以 关注公众号:IT邦德 ❤️

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐