[ 转载 ] ORACLE存储过程

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

简单的说就是专门干一件事一段sql语句。

可以由数据库自己去调用,也可以由java程序去调用。

在oracle数据库中存储过程是procedure。

二.为什么要写存储过程
1.效率高

  存储过程编译一次后,就会存到数据库,每次调用时都直接执行。而普通的sql语句我们要保存到其他地方(例如:记事本  上),都要先分析编译才会执行。所以想对而言存储过程效率更高。

2.降低网络流量

存储过程编译好会放在数据库,我们在远程调用时,不会传输大量的字符串类型的sql语句。

3.复用性高

存储过程往往是针对一个特定的功能编写的,当再需要完成这个特定的功能时,可以再次调用该存储过程。

4.可维护性高

当功能要求发生小的变化时,修改之前的存储过程比较容易,花费精力少。

5.安全性高

完成某个特定功能的存储过程一般只有特定的用户可以使用,具有使用身份限制,更安全。

三.存储过程基础
1.存储过程结构
(1).基本结构

Oracle存储过程包含三部分:过程声明,执行过程部分,存储过程异常(可写可不写,要增强脚本的容错性和调试的方便性那就写上异常处理)

(2).无参存储过程

CREATE OR REPLACE PROCEDURE demo AS/IS
    变量2 DATE;
    变量3 NUMBER;
BEGIN
    --要处理的业务逻辑
    EXCEPTION    --存储过程异常
END 

这里的as和is一样任选一个,在这里没有区别,其中demo是存储过程名称。

(3).有参存储过程

a.带参数的存储过程

CREATE OR REPLACE PROCEDURE 存储过程名称(param1 student.id%TYPE)
AS/IS
name student.name%TYPE;
age number :=20;
BEGIN
  --业务处理.....
END

上面脚本中,

第1行:param1 是参数,类型和student表id字段的类型一样。

第3行:声明变量name,类型是student表name字段的类型(同上)。

第4行:声明变量age,类型数数字,初始化为20

b.带参数的存储过程并且进行赋值

CREATE OR REPLACE PROCEDURE 存储过程名称(
       s_no in varchar,
       s_name out varchar,
       s_age number) AS
total NUMBER := 0;
BEGIN
  SELECT COUNT(1) INTO total FROM student s WHERE s.age=s_age;
  dbms_output.put_line('符合该年龄的学生有'||total||'');
  EXCEPTION
    WHEN too_many_rows THEN 
    DBMS_OUTPUT.PUT_LINE('返回值多于1行'); 
END

上面脚本中:

其中参数IN表示输入参数,是参数的默认模式。
OUT表示返回值参数,类型可以使用任意Oracle中的合法类型。
OUT模式定义的参数只能在过程体内部赋值,表示该参数可以将某个值传递回调用他的过程
IN OUT表示该参数可以向该过程中传递值,也可以将某个值传出去

第7行:查询语句,把参数s_age作为过滤条件,INTO关键字,把查到的结果赋给total变量。

第8行:输出查询结果,在数据库中“||”用来连接字符串

第9—11行:做异常处理

2.存储过程语法chengfa
(1).运算符

这里s,m,n是变量,类型是number;

 (2).SELECT INTO STATEMENT语句

该语句将select到的结果赋值给一个或多个变量,例如:

CREATE OR REPLACE PROCEDURE DEMO_CDD1 IS
s_name VARCHAR2;   --学生名称
s_age NUMBER;      --学生年龄
s_address VARCHAR2; --学生籍贯
BEGIN
  --给单个变量赋值
  SELECT student_address INTO s_address
  FROM student where student_grade=100;
   --给多个变量赋值
  SELECT student_name,student_age INTO s_name,s_age
  FROM student where student_grade=100;
  --输出成绩为100分的那个学生信息
  dbms_output.put_line('姓名:'||s_name||',年龄:'||s_age||',籍贯:'||s_address);
END

上面脚本中:

存储过程名称:DEMO_CDD1, student是学生表,要求查出成绩为100分的那个学生的姓名,年龄,籍贯

(3).选择语句

a.IF..END IF

学生表的sex字段:1-男生;0-女生

IF s_sex=1 THEN
  dbms_output.put_line('这个学生是男生');
END IF

b.IF..ELSE..END IF

IF s_sex=1 THEN
  dbms_output.put_line('这个学生是男生');
ELSE
  dbms_output.put_line('这个学生是女生');
END IF

(4).循环语句

a.基本循环

LOOP
  IF 表达式 THEN
    EXIT;
  END IF
END LOOP;

b.while循环

WHILE 表达式 LOOP
  dbms_output.put_line('haha');
END LOOP;

c.for循环

FOR a in 10 .. 20 LOOP
  dbms_output.put_line('value of a: ' || a);
END LOOP;

(5).游标

    Oracle会创建一个存储区域,被称为上下文区域,用于处理SQL语句,其中包含需要处理的语句,例如所有的信息,行数处理,等等。

    游标是指向这一上下文的区域。 PL/SQL通过控制光标在上下文区域。游标持有的行(一个或多个)由SQL语句返回。行集合光标保持的被称为活动集合。

a.下表是常用的游标属性:

属性 描述
%FOUND 如果DML语句执行后影响有数据被更新或DQL查到了结果,返回true。否则,返回false。
%NOTFOUND 如果DML语句执行后影响有数据被更新或DQL查到了结果,返回false。否则,返回true。
%ISOPEN 游标打开时返回true,反之,返回false。
%ROWCOUNT 返回DML执行后影响的行数。

b.使用游标

声明游标定义游标的名称和相关的SELECT语句:

CURSOR cur_cdd IS SELECT s_id, s_name FROM student;

打开游标游标分配内存,使得它准备取的SQL语句转换成它返回的行:

OPEN cur_cdd;

抓取游标中的数据,可用LIMIT关键字来限制条数,如果没有默认每次抓取一条:

FETCH cur_cdd INTO id, name ;

关闭游标来释放分配的内存:

CLOSE cur_cdd;


————————————————
版权声明:本文为CSDN博主「@coward」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41968788/article/details/83659164

原文地址:https://www.cnblogs.com/ILoke-Yang/p/12120477.html