Oracle存储过程、包详解

简介: Oracle存储过程、包详解

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:实际返回的行数超出请求的行数 
解决方法是:使用参照变量


目录
相关文章
|
1月前
|
SQL 存储 Oracle
一篇文章带你学会 Oracle 存储过程的基本介绍和高阶用法(上)
一篇文章带你学会 Oracle 存储过程的基本介绍和高阶用法
|
11天前
|
存储 SQL Oracle
oracle 存储过程导出sql语句 导出为文件
oracle 存储过程导出sql语句 导出为文件
|
23天前
|
Oracle Java 关系型数据库
实时计算 Flink版产品使用合集之在同步Oracle数据时,需要下载并添加到项目中的jar包主要包括哪些
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
1月前
|
SQL 存储 Oracle
一篇文章带你学会 Oracle 存储过程的基本介绍和高阶用法(下)
一篇文章带你学会 Oracle 存储过程的基本介绍和高阶用法
|
1月前
|
存储 SQL Oracle
Oracle存储过程与自定义函数的调用:异同与实战场景
【4月更文挑战第19天】Oracle的存储过程与自定义函数各有特色,存储过程用于封装复杂SQL操作,常在批量处理和数据维护中使用,通过CALL或EXECUTE调用;而自定义函数则用于简单计算和查询,返回单一值,可直接在SQL语句中调用。了解两者异同,如返回值方式、调用方式和应用场景,能提升数据库管理效率。实战场景包括:使用存储过程定期清理过期数据,用自定义函数在查询中动态计算字段值。
|
1月前
|
存储 SQL Oracle
Oracle存储过程:数据王国的魔法师
【4月更文挑战第19天】Oracle存储过程是封装复杂SQL操作的魔法工具,存储在数据库中以便重复调用。它们提供高效执行和安全,类似于预编译的程序。创建存储过程涉及定义名称和参数,如示例所示,创建一个根据员工ID获取姓名和薪资的`get_employee_info`过程。调用存储过程可提高代码可读性和性能,使数据库管理更为便捷。
|
23天前
|
Oracle 关系型数据库 Java
实时计算 Flink版操作报错之读取Oracle数据库时遇到找不到驱动,是什么原因
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
实时计算 Flink版操作报错之读取Oracle数据库时遇到找不到驱动,是什么原因
|
10天前
|
Oracle 关系型数据库 数据库
已解决:idea 连接 oracle 数据库 避雷
已解决:idea 连接 oracle 数据库 避雷
|
28天前
|
Oracle 关系型数据库 MySQL
实时计算 Flink版操作报错合集之采集oracle的时候报ORA-65040:不允许从可插入数据库内部执行该操作如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
49 3
|
3天前
|
存储 Oracle 关系型数据库
Oracle数据库快速入门
Oracle数据库快速入门
7 0