Oracle数据库之PL/SQL过程与函数

时间:2022-09-14 08:10:04

Oracle数据库之PL/SQL过程与函数

PL/SQL块分为匿名块与命名块,命名块又包含子程序、包和触发器。

过程和函数统称为PL/SQL子程序,我们可以将商业逻辑、企业规则写成过程或函数保存到数据库中,以便共享。

过程和函数均存储在数据库中,并通过参数与其调用者交换信息。过程和函数的唯一区别是函数总向调用者返回数据,而过程不返回数据。

1. 存储过程概念

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL语句集,存储在数据库中。经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。

2. 创建过程

语法:

CREATE [ OR REPLACE ] PROCEDURE [ schema. ] procedure_name
[ ( parameter_declaration [, parameter_declaration ]... ) ]
[ invoker_rights_clause ]
{ IS | AS }
{ [ declare_section ] body | call_spec | EXTERNAL} ;

说明:

procedure_name:过程名称。

parameter_declaration:参数声明,格式如下:

parameter_name [ [ IN ] datatype [ { := | DEFAULT } expression ]
| { OUT | IN OUT } [ NOCOPY ] datatype

IN:输入参数。

OUT:输出参数。

IN OUT:输入输出参数。

invoker_rights_clause:这个过程使用谁的权限运行,格式:

AUTHID { CURRENT_USER | DEFINER }

declare_section:声明部分。

body:过程块主体,执行部分。

一般只有在确认procedure_name过程是新过程或是要更新的过程时,才使用OR REPALCE关键字,否则容易删除有用的过程。

示例1:

CREATE PROCEDURE remove_emp (employee_id NUMBER) AS
tot_emps NUMBER;
BEGIN
DELETE FROM employees
WHERE employees.employee_id = remove_emp.employee_id;
tot_emps := tot_emps - 1;
END;

示例2:

CREATE OR REPLACE PROCEDURE insert_emp(
v_empno in employees.employee_id%TYPE,
v_firstname in employees.first_name%TYPE,
v_lastname in employees.last_name%TYPE,
v_deptno in employees.department_id%TYPE
)
AS
empno_remaining EXCEPTION;
PRAGMA EXCEPTION_INIT(empno_remaining, -1);
BEGIN
INSERT INTO EMPLOYEES(EMPLOYEE_ID, FIRST_NAME, LAST_NAME, HIRE_DATE,DEPARTMENT_ID)
VALUES(v_empno, v_firstname,v_lastname, sysdate, v_deptno);
DBMS_OUTPUT.PUT_LINE('插入成功!');
EXCEPTION
WHEN empno_remaining THEN
DBMS_OUTPUT.PUT_LINE('违反数据完整性约束!');
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;

3. 使用过程参数

当建立过程时,既可以指定过程参数,也可以不提供任何参数。

过程参数包括输入参数、输出参数和输入输出参数,其中输入参数(IN)用于接收调用环境的输入数据,输出参数(OUT)用于将输出数据传递到调用环境,而输入输出参数(IN OUT)不仅要接收输入数据,而且还要输出数据到调用环境。

3.1 带有输入参数的过程

通过使用输入参数,可以将应用程序数据传递到过程。当定义过程参数时,默认参数模式是输入参数,另外可以使用IN关键字显式定义输入参数。

示例:

CREATE OR REPLACE PROCEDURE insert_emp(
empno employee.empno%TYPE,
ename employee.ename%TYPE,
job employee.job%TYPE,
sal employee.sal%TYPE,
comm IN employee.comm%TYPE,
deptno IN employee.deptno%TYPE
)
IS
BEGIN
INSERT INTO employee VALUES(empno, ename, job, sal, comm, depno);
END;

3.2 带有输出参数的过程

通过在过程中使用输出参数,可以将数据或消息传递到调用环境和应用程序。当定义输出参数时,需要指定参数模式OUT。

示例:

CREATE OR REPLACE PROCEDURE update_sal(
eno NUMBER,
salary NUMBER,
name out VARCHAR2)
IS
BEGIN
UPDATE employee SET sal=salary WHERE empno=eno
RETURNING ename INTO name;
END;

3.3 带有输入输出参数的过程

通过在过程中使用输入输出参数,可以在调用过程时输入数据到过程,在调用结束后输出数据到调用环境和应用程序。当定义输入输出参数时,需要指定参数模式为IN OUT。

示例:

CREATE OR REPLACE PROCEDURE divide(
num1 IN OUT NUMBER,
num2 IN OUT NUMBER)
IS
v1 NUMBER;
v2 NUMBER;
BEGIN
v1 := trunc(num1 / num2);
v2 := mod(num1,num2);
num1 := v1;
num2 := v2;
END;

4. 调用过程

当在SQL*PLUS中调用过程时,需要使用CALL或者EXECUTE命令,而在PL/SQL块中过程可以直接引用。

ORACLE使用EXECUTE语句来调用存储过程语法:

EXEC[UTE] procedure_name(parameter1, parameter2, …);

示例1:

-- 调用删除员工的过程
EXEC remove_emp(1); -- 调用插入员工的过程
EXECUTE insert_emp(1, 'tommy', 'lin', 2);

示例2:

DECLARE
v_name employee.ename%type;
BEGIN
update_sal(&eno,&salary,v_name);
dbms_output.put_line('姓名:'||v_name);
END;

5. 函数介绍

函数是一段独立的PL/SQL程序代码,它执行某个特定的、明确的任务。通常,函数将处理从程序的调用部分传递给它的信息,然后返回单个值。信息通过称为参数的特殊标识符传递给函数,然后通过RETURN语句返回。

6. 创建函数

语法:

CREATE [ OR REPLACE ] FUNCTION [ schema. ] function_name
[ ( parameter_declaration [, parameter_declaration]... )
]
RETURN datatype
[ { invoker_rights_clause
| DETERMINISTIC
| parallel_enable_clause
| RESULT_CACHE [ relies_on_clause ]
}...
]
{ { AGGREGATE | PIPELINED } USING [ schema. ] implementation_type
| [ PIPELINED ] { IS | AS } { [ declare_section ] body
| call_spec
| EXTERNAL
}
} ;

示例1:

CREATE FUNCTION get_bal(acc_no IN NUMBER)
RETURN NUMBER
IS
acc_bal NUMBER(11,2);
BEGIN
SELECT order_total INTO acc_bal FROM orders
WHERE customer_id = acc_no;
RETURN(acc_bal);
END;

函数参数也有输入、输出、输入输出三种模式:IN、OUT、IN OUT是形参的模式。若省略,则为IN模式。

和过程一样,IN模式的形参只能将实参传递给形参,进入函数内部,但只能读不能写,函数返回时实参的值不变。

OUT模式的形参会忽略调用时的实参值(或说该形参的初始值总是NULL),但在函数内部可以被读或写,函数返回时形参的值会赋予给实参。

IN OUT具有前两种模式的特性,即调用时,实参的值总是传递给形参,结束时,形参的值传递给实参。

调用时,对于IN模式的实参可以是常量或变量,但对于OUT和IN OUT模式的实参必须是变量。

示例2:

CREATE OR REPLACE FUNCTION get_salary(
dept_no IN NUMBER DEFAULT 1,
emp_count OUT NUMBER)
RETURN NUMBER
IS
V_sum NUMBER;
BEGIN
SELECT SUM(SALARY), count(*) INTO V_sum, emp_count FROM EMPLOYEES
WHERE DEPARTMENT_ID=dept_no;
RETURN v_sum;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('数据不存在');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('其它异常:');
DBMS_OUTPUT.PUT_LINE('错误号:' || SQLCODE||',错误消息:'||SQLERRM);
END get_salary;

7. 函数调用

语法:

function_name([[parameter_name1 =>] value1[, [parameter_name2 =>] value2, ...]]);

示例1:

DECLARE
v_num NUMBER;
v_sum NUMBER;
BEGIN
v_sum := get_salary(27, v_num);
DBMS_OUTPUT.PUT_LINE('部门27的工资总和:'||v_sum||',人数为:'||v_num);
END;

示例2:

DECLARE
v_num NUMBER;
v_sum NUMBER;
BEGIN
v_sum := get_salary(dept_no => 27, emp_count => v_num);
DBMS_OUTPUT.PUT_LINE('部门27的工资总和:'||v_sum||',人数为:'||v_num);
END;

示例3:

DECLARE
v_num NUMBER;
v_sum NUMBER;
BEGIN
v_sum := get_salary(emp_count => v_num);
DBMS_OUTPUT.PUT_LINE('部门27的工资总和:'||v_sum||',人数为:'||v_num);
END;

8. 删除过程或函数

删除过程语法:

DROP PROCEDURE [schema.]procudure_name;

删除函数语法:

DROP FUNCTION [schema.]function_name;

9. 过程与函数比较

过程 函数
作为PL/SQL语句执行 作为表达式的一部分执行
在规范中不包含RETURN子句 必须在规范中包含RETURN子句
不返回任何值 必须返回单个值
可以RETURN语句,但是与函数不同,它不能用于返回值 必须包含至少一条RETURN语句

过程与函数的相同功能有:

  1. 都使用IN模式的参数传入数据、OUT模式的参数返回数据。
  2. 输入参数都可以接受默认值,都可以传值或传引导。
  3. 调用时的实际参数都可以使用位置表示法、名称表示法或组合方法。
  4. 都有声明部分、执行部分和异常处理部分。
  5. 其管理过程都有创建、编译、授权、删除、显示依赖关系等。

Oracle数据库之PL/SQL过程与函数的更多相关文章

  1. Oracle数据库之PL/SQL包

    Oracle数据库之PL/SQL包 1. 简介 包(PACKAGE)是一种数据对象,它是一组相关过程.函数.变量.常量和游标等PL/SQL程序设计元素的组合,作为一个完整的单元存储在数据库中,用名称来 ...

  2. Oracle数据库之PL/SQL触发器

    Oracle数据库之PL/SQL触发器 1. 介绍 触发器(trigger)是数据库提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是 ...

  3. Oracle数据库之PL/SQL异常处理

    Oracle数据库之PL/SQL异常处理 异常指的是在程序运行过程中发生的异常事件,通常是由硬件问题或者程序设计问题所导致的. PL/SQL程序设计过程中,即使是写得最好的程序也可能会遇到错误或未预料 ...

  4. Oracle数据库之PL/SQL流程控制语句

    Oracle数据库之PL/SQL流程控制语句 在任何计算机编程语言(如C,Java,C#等)都有各种流程控制语句,同样,在PL/SQL中也存在这样的流程控制结构. 几种常见的流程控制结构: 一.条件结 ...

  5. Oracle数据库之PL/SQL程序设计简介

    PL/SQL程序设计简介 一.什么是PL/SQL? PL/SQL是 Procedure Language & Structured Query Language 的缩写. ORACLE的SQL ...

  6. oracle数据库之PL/SQL 块结构和组成元素

    一.PL/SQL 块 (一)PL/SQL 程序由三个块组成,即声明部分.执行部分.异常处理部分 PL/SQL 块的结构如下: 1.DECLARE /* 声明部分: 在此声明 PL/SQL 用到的变量, ...

  7. Oracle数据库之PL/SQL基础

    介绍PL/SQL之前,先介绍一个图像化工具:Oracle SQL Developer 在oracle的开发过程中, 我们难免会使用第三方开发的软件来辅助我们书写SQL, pl/sql是一个不错的sql ...

  8. Oracle数据库之PL/SQL程序设计基础

    PL/SQL程序设计基础 一.PL/SQL块结构 前边我们已经介绍了PL/SQL块的结构,再来回顾一下: DECLARE /* * 声明部分——定义常量.变量.复杂数据类型.游标.用户自定义异常 */ ...

  9. ORACLE数据库之PL/SQL触发器、rownum、动态SQL、数据库之视图与索引

    WHEN子句说明触发约束条件.Condition为一个逻辑表达时,其中必须包含相关名称,而不能包含查询语句,也不能调用PL/SQL函数.WHEN子句指定的触发约束条件只能用在BEFORE和AFTER行 ...

随机推荐

  1. Repeater 双向排序

      做项目的时候,DataGrid ,DataList,Repeater 三个控件都是很优秀的数据显示控件,DataGrid的方便,简单易用,功能强大,但对性能会有所影响,在loading页面的时候大 ...

  2. POJ 3461 裸的KMP

    直接贴代码吧 #include<cstdio> #include<cstring> ],T[]; ]; int n,m; void getfail() { f[] = ; f[ ...

  3. 【web性能】让css更简洁、高效

    用了这么多年的CSS,现在才明白CSS的真正匹配原理,不知道你是否也跟我一样?   看1个简单的CSS: DIV#divBox p span.red{color:red;},按习惯我们对这个CSS 的 ...

  4. 索引列上的统计 &lt&semi;第一篇&gt&semi;

    一.索引在查询优化中的角色 SQL Server的查询优化器是基于开销的优化器.它通过确认选择性.数据的唯一性以及过滤数据(通过WHERE或JOIN子句)所使用的列来决定最佳的数据访问机制.统计与索引 ...

  5. HDU-problem-1002-人类史上最大最好的希望事件-矩阵快速幂

    Problem Description 作为CNCS的半壁*,狗哥常常在宇宙中心邵阳眺望黄浦江,夜晚的星空总是迷人,有时候还能见到彗星滑落. 狗哥是幸运的,他在两秒钟内看到了十七颗彗星划过天际,作为 ...

  6. Django 的认识,面试题

    Django 的认识,面试题 1. 对Django的认识? #1.Django是走大而全的方向,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构.以及全 ...

  7. python的特殊方法介绍

    __repr__.__str__ __len__.__getitem__.__setitem__.__delitem__.__contains__ __iter__.__reversed__.__ne ...

  8. eclipse操作(备忘)

    myecplise破解   https://blog.csdn.net/by_xiaobai007/article/details/81177367 1.查看类路径 2.建立模板 window--pr ...

  9. centos7 二进制版本安装 mysql8&period;0&period;13

    一.下载mysql二进制安装包 mysql官网: https://dev.mysql.com/downloads/mysql/ 由于国内网络问题,个人建议使用国内开源镜像站下载: http://mir ...

  10. Scrum立会报告&plus;燃尽图(十二月五日总第三十六次):Final阶段分配任务

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2284 项目地址:https://git.coding.net/zhang ...