数据库存储过程(Stored Procedure)是一种在数据库中存储的SQL语句集合,它封装了一组预编译的SQL语句,用于执行特定的任务。存储过程可以接受输入参数,并且可以返回输出参数。使用存储过程可以提高数据库操作的效率、减少网络流量、增强代码的重用性和安全性。
特点和组成部分的解析
Ⅰ、定义和创建存储过程
在Oracle数据库中,创建存储过程的基本语法如下:
sql复制
CREATE [OR REPLACE] PROCEDURE 存储过程名 (
参数1 数据类型 [IN | OUT | IN OUT],
参数2 数据类型 [IN | OUT | IN OUT],
...
) IS
-- 声明变量
BEGIN
-- 存储过程的主体部分,包含SQL语句和PL/SQL代码
EXCEPTION
-- 异常处理部分
END;
CREATE OR REPLACE:
CREATE
用于创建新的存储过程,OR REPLACE
表示如果存储过程已存在,则替换它。存储过程名:存储过程的名称,用于在应用程序中调用。
参数:存储过程可以接受输入参数(IN)、输出参数(OUT)或输入输出参数(IN OUT)。
IS:表示存储过程的定义开始。
BEGIN ... END:存储过程的主体部分,包含SQL语句和PL/SQL代码。
EXCEPTION:异常处理部分,用于捕获和处理运行时错误。
Ⅱ、参数类型
IN:输入参数,用于向存储过程传递值。
OUT:输出参数,用于从存储过程返回值。
IN OUT:既可以传递值给存储过程,也可以从存储过程返回值。
Ⅲ、示例
假设有一个employees
表,我们想创建一个存储过程来插入一条新的员工记录,并返回新插入的员工ID。
sql复制
CREATE OR REPLACE PROCEDURE insert_employee (
p_first_name IN VARCHAR2,
p_last_name IN VARCHAR2,
p_email IN VARCHAR2,
p_phone_number IN VARCHAR2,
p_hire_date IN DATE,
p_job_id IN VARCHAR2,
p_salary IN NUMBER,
p_manager_id IN NUMBER,
p_department_id IN NUMBER,
p_employee_id OUT NUMBER
) IS
BEGIN
INSERT INTO employees (first_name, last_name, email, phone_number, hire_date, job_id, salary, manager_id, department_id)
VALUES (p_first_name, p_last_name, p_email, p_phone_number, p_hire_date, p_job_id, p_salary, p_manager_id, p_department_id)
RETURNING employee_id INTO p_employee_id;
END;
Ⅳ、调用存储过程
在Oracle中,可以使用EXECUTE
或EXEC
命令来调用存储过程。例如:
sql复制
DECLARE
v_employee_id NUMBER;
BEGIN
insert_employee (
p_first_name => 'John',
p_last_name => 'Doe',
p_email => 'john.doe@example.com',
p_phone_number => '123-456-7890',
p_hire_date => TO_DATE('2025-01-01', 'YYYY-MM-DD'),
p_job_id => 'IT_PROG',
p_salary => 5000,
p_manager_id => 100,
p_department_id => 60,
p_employee_id => v_employee_id
);
DBMS_OUTPUT.PUT_LINE('新插入的员工ID: ' || v_employee_id);
END;
Ⅴ、优点
性能提升:存储过程在数据库服务器上预编译,执行效率高,减少了网络流量。
代码重用:存储过程可以被多个应用程序调用,提高了代码的重用性。
安全性:通过存储过程可以限制对数据库的直接访问,增强数据的安全性。
事务管理:存储过程可以包含多个SQL语句,并且可以进行事务管理,确保数据的一致性。
Ⅵ、缺点
维护成本:存储过程的代码在数据库中,可能需要数据库管理员或开发人员进行维护。
可移植性:存储过程的语法和功能在不同的数据库系统中可能有所不同,影响代码的可移植性。
存储过程是数据库编程中的一个重要工具,合理使用可以显著提高应用程序的性能和可维护性。
一、存储过程模板公式
create [or replace] PROCEDURE 过程名(参数列表)
AS
PLSQL子程序体; (关键字可以小写)(如果不传参,则参数列表的小括号也可以省略)
这个PLSQL子程序体;一般为:
begin
代码...
end;
/
如果写的是存储函数,那么这里的PROCEDURE需要改成FUNCTION,而且必须在参数列表和AS之间添加一句:RETURN 函数值类型
。而且需要在子程序体需要返回的时候写return 返回值
。
写好之后先编译,然后调用、运行。
as后面跟的是说明部分,相当于declare。
as也可以写成is。
调用方式有两种:
(1)exec 过程名();
(2)
begin
调用语句;
end;
/
二、入参
在参数列表中,如果是输入参数,可以写入eno in number,in是关键,in前面是变量名,后面是变量类型。
三、出参
如果是输出参数,写eno out number,out是关键,out前面是变量名,后面是变量类型。
存储过程和存储函数都可以有out参数。
他们都可以有多个out参数。
存储过程可以通过out参数来实现返回值。
四、小例子
查询某个员工姓名、月薪和职位
create or replace procedure queryempinform(eno in number,
pename out varchar2,
psal out number,
pjob out varchar2)
as
begin
--得到该员工的姓名、月薪和职位
select ename,sal,empjob into pename,psal,pjob from emp where empno=eno;
end;
/
五、在out参数中使用光标案例
案例:查询某个部门中所有员工的所有信息。
包头(负责声明包中的结构):
CREATE OR REPLACE PACKAGE MYPACKAGE AS
type empcursor is ref cursor;
procedure queryEmpList(dno in number,empList out empcursor);
END MYPACKAGE;
注意:包头中也可以不定义存储过程,只定义光标那一行。
包体(负责写需要实现包头中声明的所有方法):
CREATE OR REPLACE PACKAGE BODY MYPACKAGE AS
procedure queryEmpList(dno in number,empList out empcursor) AS
BEGIN
--打开光标类型(是一个集合,意味着可以返回许多信息的集合)
open empList for select * from emp where deptno=dno;
END queryEmpList;
END MYPACKAGE;
注意:包体里面的存储过程也可以不写在包体内部也可以一样调用包头中定义的光标。
六、其他小知识点
参数列表可以换行,也可以在关键字之间多加空格。
如果是没有参数的就是存储过程,如果有参数就是存储函数。存储函数可以有一个返回值,可以用return子句进行返回。
我们的原则是,如果只需要一个返回值,则用存储函数。如果没有返回值,用存储过程,如果需要有多个返回值,则使用存储过程,在参数中使用out参数。
单行注释使用“--注释内容”,多行注释使用“/* 注释内容 */”。
调试的时候授予权限:
哪个权限没有就到sqlplus输入如下代码:
grant 要调的权限(中间用逗号分隔) to 用户名;
如果在计算中可能会有空值的话需要使用nvl预空函数。
七、简单EXISTS和 NOT EXISTS讲解和案例
以
select * from A where exists(select * from B where A.a=B.a)
为例,
exists表示,对于A中的每一个记录,如果,在表B中有记录,其属性a的值与表A这个记录的属性a的值相同,则表A的这个记录是符合条件的记录,
如果是NOT exists,则表示如果表B中没有记录能与表A这个记录连接,则表A的这个记录是符合条件的记录。