Oracle存储过程语法学习

article/2025/9/16 22:46:16

Oracle存储过程:

1.1 第一个存储过程

--创建存储过程

create or replace procedure proc1(   

  p_para1 varchar2,   

  p_para2 out varchar2,   

  p_para3 in out varchar2   

)as    

 v_name varchar2(20);   

begin   

  v_name := '张三';   

  p_para3 := v_name;   

  dbms_output.put_line('p_para3:'||p_para3);   

end;

 

上面就是一个最简单的存储过程。一个存储过程大体分为这么几个部分: 
创建语句:create or replace procedure 存储过程名 
如果没有or replace语句,则仅仅是新建一个存储过程。如果系统存在该存储过程,则会报错。Create or replace procedure 如果系统中没有此存储过程就新建一个,如果系统中有此存储过程则把原来删除掉,重新创建一个存储过程。 
存储过程名定义:包括存储过程名和参数列表。参数名和参数类型。参数名不能重复, 参数传递方式:IN, OUT, IN OUT 
IN 表示输入参数,按值传递方式。 
OUT 表示输出参数,可以理解为按引用传递方式。可以作为存储过程的输出结果,供外部调用者使用。 
IN OUT 即可作输入参数,也可作输出参数。 
参数的数据类型只需要指明类型名即可,不需要指定宽度。 
参数的宽度由外部调用者决定。 
过程可以有参数,也可以没有参数 
变量声明块:紧跟着的as (is )关键字,可以理解为pl/sql的declare关键字,用于声明变量。 
变量声明块用于声明该存储过程需要用到的变量,它的作用域为该存储过程。另外这里声明的变量必须指定宽度。遵循PL/SQL的变量声明规范。 
过程语句块:从begin 关键字开始为过程的语句块。存储过程的具体逻辑在这里来实现。 
异常处理块:关键字为exception ,为处理语句产生的异常。该部分为可选 
结束块:由end关键字结果。

 

1.2 存储过程的参数传递方式 
存储过程的参数传递有三种方式:IN,OUT,IN OUT . 
IN 按值传递,并且它不允许在存储过程中被重新赋值。如果存储过程的参数没有指定存参数传递类型,默认为IN

这一点与其它高级语言都不同。它相当于java在参数前面加上final关键字。

 

OUT 参数:作为输出参数,需要注意,当一个参数被指定为OUT类型时,就算在调用存储过程之前对该参数进行了赋值,在存储过程中该参数的值仍然是null.

 

INOUT 是真正的按引用传递参数。即可作为传入参数也可以作为传出参数。

 

-----------------------------------------------------------------------

-----------------------------------------------------------------------

Oracle存储过程语法学习:

 

存储过程创建语法:

       create or replace procedure 存储过程名(param1 in type,param2 out type)

as

变量1 类型(值范围);

变量2 类型(值范围);

Begin

    Select count(*) into 变量1 from 表A where列名=param1;

    If (判断条件) then

       Select 列名 into 变量2 from 表A where列名=param1;

       Dbms_output.Put_line(‘打印信息’);

    Elsif (判断条件) then

       Dbms_output.Put_line(‘打印信息’);

    Else

       Raise 异常名(NO_DATA_FOUND);

    End if;

Exception

    When others then

       Rollback;

End;

 

注意事项:

1、  存储过程参数不带取值范围,in表示传入,out表示输出

2、  变量带取值范围,后面接分号

3、  在判断语句前最好先用count(*)函数判断是否存在该条操作记录

4、  用select 。。。into。。。给变量赋值

5、  在代码中抛异常用 raise+异常名

 

以命名的异常:

命名的系统异常                          产生原因

ACCESS_INTO_NULL                   未定义对象

CASE_NOT_FOUND                     CASE 中若未包含相应的 WHEN ,并且没有设置ELSE 时

COLLECTION_IS_NULL                集合元素未初始化

CURSER_ALREADY_OPEN            游标已经打开

DUP_VAL_ON_INDEX                   唯一索引对应的列上有重复的值

INVALID_CURSOR                       在不合法的游标上进行操作

INVALID_NUMBER                        内嵌的 SQL 语句不能将字符转换为数字

NO_DATA_FOUND                        使用 select into 未返回行,或应用索引表未初始化的 

 

TOO_MANY_ROWS                      执行 select into 时,结果集超过一行

ZERO_DIVIDE                              除数为 0

SUBSCRIPT_BEYOND_COUNT        元素下标超过嵌套表或 VARRAY 的最大值

SUBSCRIPT_OUTSIDE_LIMIT         使用嵌套表或 VARRAY 时,将下标指定为负数

VALUE_ERROR                             赋值时,变量长度不足以容纳实际数据

LOGIN_DENIED                             PL/SQL 应用程序连接到 oracle 数据库时,提供了不正确的用户名或密码

NOT_LOGGED_ON                         PL/SQL 应用程序在没有连接 oralce 数据库的情况下访问数据

PROGRAM_ERROR                         PL/SQL 内部问题,可能需要重装数据字典& pl./SQL系统包

ROWTYPE_MISMATCH                    宿主游标变量与 PL/SQL 游标变量的返回类型不兼容

SELF_IS_NULL                              使用对象类型时,在 null 对象上调用对象方法

STORAGE_ERROR                         运行 PL/SQL 时,超出内存空间

SYS_INVALID_ID                           无效的 ROWID 字符串

TIMEOUT_ON_RESOURCE               Oracle 在等待资源时超时

 

oracle 存储过程的基本语法:

1.基本结构 
CREATE OR REPLACE PROCEDURE 存储过程名字
(
    参数1 IN NUMBER,
    参数2 IN NUMBER
) IS
变量1 INTEGER :=0;
变量2 DATE;
BEGIN

END 存储过程名字

2.SELECT INTO STATEMENT
  将select查询的结果存入到变量中,可以同时将多个列存储多个变量中,必须有一条
  记录,否则抛出异常(如果没有记录抛出NO_DATA_FOUND)
  例子: 
  BEGIN
  SELECT col1,col2 into 变量1,变量2 FROM typestruct where xxx;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
      xxxx;
  END;
  ...

3.IF 判断
  IF V_TEST=1 THEN
    BEGIN 
       do something
    END;
  END IF;

4.while 循环
  WHILE V_TEST=1 LOOP
  BEGIN
       XXXX
  END;
  END LOOP;

5.变量赋值
  V_TEST := 123;

6.用for in 使用cursor
  ...
  IS
  CURSOR cur IS SELECT * FROM xxx;
  BEGIN
 FOR cur_result in cur LOOP
  BEGIN
   V_SUM :=cur_result.列名1+cur_result.列名2
  END;
 END LOOP;
  END;

7.带参数的cursor
  CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE TYPEID=C_ID;
  OPEN C_USER(变量值);
  LOOP
 FETCH C_USER INTO V_NAME;
 EXIT FETCH C_USER%NOTFOUND;
    do something
  END LOOP;
  CLOSE C_USER;

8.用pl/sql developer debug
  连接数据库后建立一个Test WINDOW
  在窗口输入调用SP的代码,F9开始debug,CTRL+N单步调试

 

关于oracle存储过程的若干问题备忘:

1.在oracle中,数据表别名不能加as,如:

select a.appname from appinfo a;-- 正确
select a.appname from appinfo as a;-- 错误

 也许,是怕和oracle中的存储过程中的关键字as冲突的问题吧

 

2.在存储过程中,select某一字段时,后面必须紧跟into,如果select整个记录,利用游标的话就另当别论了。

  select af.keynode into kn from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;-- 有into,正确编译
  select af.keynode from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;-- 没有into,编译报错,提示:Compilation 
  Error: PLS-00428: an INTO clause is expected in this SELECT statement
 

3.在利用select...into...语法时,必须先确保数据库中有该条记录,否则会报出"no data found"异常。

   可以在该语法之前,先利用select count(*) from 查看数据库中是否存在该记录,如果存在,再利用select...into...

 

4.在存储过程中,别名不能和字段名称相同,否则虽然编译可以通过,但在运行阶段会报错

 select keynode into kn from APPFOUNDATION where appid=aid and foundationid=fid;-- 正确运行
select af.keynode into kn from APPFOUNDATION af where af.appid=appid and af.foundationid=foundationid;-- 运行阶段报错,提示
ORA-01422:exact fetch returns more than requested number of rows

 

5.在存储过程中,关于出现null的问题

假设有一个表A,定义如下:

create table A(
id varchar2(50) primary key not null,
vcount number(8) not null,
bid varchar2(50) not null -- 外键 
);

如果在存储过程中,使用如下语句:

select sum(vcount) into fcount from A where bid='xxxxxx';

如果A表中不存在bid="xxxxxx"的记录,则fcount=null(即使fcount定义时设置了默认值,如:fcount number(8):=0依然无效,fcount还是会变成null),这样以后使用fcount时就可能有问题,所以在这里最好先判断一下:

if fcount is null then
    fcount:=0;
end if;

这样就一切ok了。

6.Hibernate调用oracle存储过程

this.pnumberManager.getHibernateTemplate().execute(
       new HibernateCallback() {
             public Object doInHibernate(Session session)
                     throws HibernateException, SQLException {
                 CallableStatement cs = session.connection()
                         .prepareCall("{call modifyapppnumber_remain(?)}");
                 cs.setString(1, foundationid);
                 cs.execute();
                 return null;
              }
          });

转载:http://www.cnblogs.com/ZRJ-boke/p/6610524.html


http://chatgpt.dhexx.cn/article/HdijZl6w.shtml

相关文章

sql存储过程语法详解

一、定义变量 使用关键字declare申明变量: declare 变量名 变量类型 /*简单赋值*/declare a intset a5print a/*select赋值*/declare b nvarchar(10) select b stu_name from dbo.student where stu_id6 print b/*update赋值*/declare c nvarchar(10) upd…

MySQL常用操作之创建存储过程语法详解

MySQL常用操作之创建存储过程语法详解 前言简介语法创建结构变量结构入参变量和出参变量流程控制判断(IF 语句)判断(CASE 语句)循环(LOOP 语句)循环(WHILE 语句)循环(REPEAT 语句)再次循环(ITERATE 语句) 总结参考链接 前言 场景介绍 作为一名Java搬运工,实际开发中…

Oracle 存储过程语法

Oracle 存储过程语法 1. 创建表(测试数据准备) -- 创建用户表 create table TT_USER (USERID NUMBER(10),USERNAME VARCHAR2(255),PASSWORD VARCHAR2(255),SEX VARCHAR2(1) );INSERT INTO TT_USER VALUES (101, zhang, 111, 1); INSERT INTO TT…

mysql存储过程基本语法

本文来说下mysql存储过程基本语法 文章目录 基本语法使用实例变量的使用变量定义declare语句变量赋值用户变量 存储过程的参数in 输入参数out 输出参数inout输入输出参数 本文小结 基本语法 存储过程就是具有名字的一段代码,用来完成一个特定的功能。创建的存储过程…

Oracle存储过程基本语法

后来者居上,不是easy的事情 尤其技术类work,更加如此。都是have one 投入的过程的。尤其开发,还是属于技术壁垒挺高的行业。 创建基本的存储过程 1 CREATE OR REPLACE PROCEDURE MyProName IS 2 BEGIN 3 NULL; 4 END; 行1:CREATE OR REPL…

存储过程常见语法

存储过程常见语法 一、存储过程的概念: 1、存储过程Procedure是一组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称并给出参数来执行 2、存储过程中可以包含逻辑控制语句和数据操纵语句,它可以接受参数…

存储过程的语法讲解

在上一篇文章:别再说不知道什么是存储过程和存储函数了 中简单的介绍了存储过程和存储函数以及其使用。其实存储过程是可以进行编程的,所以可以和其他的编程语言一样使用变量、表达式以及控制结构进行编程,从而实现一些复杂和有用的功能。这篇…

子网掩码的作用

IP地址由网络和主机两部分标识组成 IP地址由“网络标识(网络地址)”和“主机标识(主机地址)”两部分组成。在局域网内相互间通信的网络必须具有相同网络地址,也叫相同的网段,在同一个网段内每个设备的主机…

子网掩码使用详解

一、子网掩码 IP地址是以网络号和主机号来标示网络上的主机的,我们把网络号相同的主机称之为本地网络,网络号不相同的主机称之为远程网络主机,本地网络中的主机可以直接相互通信;远程网络中的主机要相互通信必须通过本地网关&…

什么是子网掩码 子网掩码的作用是什么?

什么是子网掩码 子网掩码的作用是什么? 网络工作人员经常需要与ip和子网掩码等打交道,相信绝大数的朋友都知道IP的意思,但是还不理解子网掩码的意思,下面装机之家小编来为大家介绍下关于子网掩码的相关知识,希望能够对…

ip、子网掩码、网关、默认网关

这里写目录标题 ip网络地址主机地址 子网子网掩码子网掩码的表示方法为什么要使用子网掩码?子网掩码的分类 网关默认网关 ip ip地址 网络地址 主机地址(又称:网络号和主机号),我们把网络号相同的主机称之为本地网络…

子网划分和子网掩码

目录 前言 1、IP地址 1.1 IP地址的内容 1.2 IP地址的分类 2、子网掩码的作用 2.1 主机间的通信 2.2 子网掩码 3.子网划分 3.1 子网划分的原因 3.2 子网划分的原理 3.3 IP地址汇总 总结 前言 知道IP地址的分类和基本使用,如果公司拥有300台计算机&#xf…

子网掩码详解

IP地址 IP地址被用来给Internet上的电脑一个编号。大家日常见到的情况是每台联网的PC上都需要有IP地址,才能正常通信。我们可以把“个人电脑”比作“一台电话”,那么“IP地址”就相当于“电话号码”,而Internet中的路由器,就相当于…

子网掩码的两种计算方式

(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/70946041冷血之心的博客) 关注微信公众号(文强的技术小屋),学习更多技术知识,一起遨游知识海洋~ …

子网掩码的划分和计算详解

一、子网掩码的计算 TCP/IP网间网技术产生于大型主流机环境中,它能发展到今天的规模是当初的设计者们始料未及的。网间网规模的迅速扩展对IP地址模式的威胁并不是它不能保证主机地址的唯一性,而是会带来两方面的负担:第一,巨大的…

一文带你了解什么是子网掩码

什么是子网掩码 子网掩码代表了“网络号子网号”与主机号之间的分割方案。 很晦涩? 说子网掩码,我们还得先说说IP地址。 什么是IP地址 因特网上的每台主机或路由器端口都必须有一个唯一的IP地址。因为IP地址,在网络上我们才能互相识别&a…

制作QQ登录界面(UI版)

工具&#xff1a;Android Studio activity_main.xml <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http:…

html登录界面

今天是2019年11月14日我第一次注册博客&#xff0c;我把我做的一个登陆界面分享给大家看希望各位大佬指教。 首先是html文件。 1.登录界面html 登录界面 用户名: 密 码: 注册 2.注册界面html。 注册界面 用户名: 输入密码: 确认密码: 立刻注册返回登录 **3.效果图**! 欢迎…

Android仿QQ微信开场导航以及登陆界面

相信大家对于微信等社交应用的UI界面已经都很熟悉了&#xff0c;该UI最值得借鉴的莫过于第一次使用的时候一些列产品介绍的图片&#xff0c;可以左右滑动浏览&#xff0c;最后进入应用&#xff0c;这一效果适用于多种项目中&#xff0c;相信今后开发应用一定会用得到。网路上也…

[练习]QQ登陆界面-测试用例的编写

&#xff08;Test Case&#xff09;是为了实施测试而向被测试系统提供的一组集合&#xff0c; 包括&#xff1a;测试环境、操作步骤、测试数据、预期结果等要素。 一条测试用例最终只有一个结果。 一个功能点至少有一个测试用例。 测试用例数/功能点数 测试的覆盖率&#xf…