二十一、JAVA调用存储过程(Oracle专栏)

news/2024/5/14 12:37:19/文章来源:https://blog.csdn.net/nanyangnongye/article/details/127254141
2022年9月28日16:33:11

目录

🏆一、存储过程的创建及调用

⭐️1.1、PLSQL编程

⭐️1.2、程序结构

⭐️1.3、变量

1.3.1、普通变量

1.3.2、引用型变量

1.3.3、记录型变量

⭐️1.4、流程控制

1.4.1、条件分支

1.4.2、循环

🏆二、游标

⭐️2.1、什么是游标

⭐️2.2、语法

⭐️2.3、游标的属性

⭐️2.4、创建和使用

⭐️2.5、带参数的游标

🏆三、存储过程

⭐️3.1、概念作用

⭐️3.2、语法

⭐️3.3、输入带参数的存储过程

⭐️3.4、带输出参数的存储过程

⭐️3.5、Java程序调用存储过程



🏆一、存储过程的创建及调用

  1. PLSQL编程:HelloWorld,程序结构、变量、流程控制、游标。

  2. 存储过程:概念、无参存储、有参存储(输入、输出)

  3. JAVA调用存储过程

⭐️1.1、PLSQL编程

什么是PL/SQL?

  1. PL/SQL (Procedure Language/SQL)

  2. PLSQL是Oracle对sql语言的过程化扩展(类似于Basic)

  3. 指在sql命令语言中增加了过程处理语句(如分支、循环等),使sql语言具有过程处理能力。

⭐️1.2、程序结构

通过PIsqI Developer工具的Test Window创建程序模版或者通过语句在SQL Window编写

提示:PLSQL语言的大小写是不区分的

PL/SQL可以分为三个部分:声明部分、可执行部分、异常处理部分。

-- Created on 2022/10/8 by ME666 
declare -- 声明游标、变量i integer;
begin-- 执行语句-- 异常处理end;

其中Declare部分用来声明变量或游标(结果类型变量),如果程序中无变量声明可以省略掉

1.3、Hello World

​
BEGINDBMS_OUTPUT.PUT_LINE('hello world');
END;
​

其中 DBMS_OUTPUT为Oracle的内置程序包,相当于Java中的System.out,而PUT_LINE是调用的方法,相当于Java中的println()方法

在SQLplus中也可以编写运行PLSQL程序

SQL> BEGIN2    DBMS_OUTPUT.PUT_LINE('hello world');3  END;4  /

执行结束后并显示输出的结果,默认情况下,输出选项是关闭状态,我们需要开启一下set serveroutput on

⭐️1.3、变量

PLSQL编程中常见的变量分两大类

  1. 普通数据类型(char,varchar2,date,number,boolean,long)

  2. 特殊变量类型(引用型变量,记录型变量)

变量声明的方式为

变量名 变量类型(变量长度) eg: v_name varchar(20);

1.3.1、普通变量

变量赋值的方式有两种:

  1. 直接赋值语句 := 比如:v_name := '张三'

  2. 语句赋值,使用select...into...赋值:(语法 select 值 into 变量)

示例:打印人员个人信息,包括:姓名、薪水、地址

-- 打印人员个人信息,包括:姓名、薪水、地址
declare-- 姓名v_name varchar(20) := '张三';-- 薪水v_salary number;-- 地址v_address varchar2(200);
BEGIN-- 直接赋值v_salary := 7000;-- 语句赋值select '北凉州北凉府北凉人北凉王' into v_address from dual;DBMS_OUTPUT.PUT_LINE('姓名:' || v_name || '-' ||'薪水:' || v_salary || '-' ||'地址:' || v_address);
END;
​

1.3.2、引用型变量

变量的类型和长度取决于表中字段的类型和长度

通过表名.列名%TYPE指定变量的类型和长度,语法:变量名 表名.列名%TYPE。例如:v_name emp.name%Type

示例:查询emp表中7839员工的个人信息,打印姓名和薪水

-- Created on 2022/10/8 by ME666 
DECLARE
​V_NAME   EMP.ENAME%TYPE; -- 姓名V_SALARY EMP.SAL%TYPE; -- 薪水BEGIN-- 查询表中的姓名和薪水并赋值给变量-- 注意查询的字段和赋值的变量的顺序、个数、类型要一致SELECT ENAME, SAL INTO V_NAME, V_SALARY FROM EMP WHERE EMPNO = 7839;-- 打印变量DBMS_OUTPUT.PUT_LINE('姓名为:' || V_NAME || '薪水为:' || V_SALARY);END;
​

1.3.3、记录型变量

接收表中的一整行记录,相当于Java中的一个对象

语法:变量名称 表名%ROWTYPE,列如:v_emp emp%ROWTYPE

示例:查询并打印7839号员工的姓名和薪水

-- 查询并打印7839号员工的姓名和薪水
​
DECLARE
​V_EMP EMP%ROWTYPE;
​
BEGIN
​SELECT * INTO V_EMP FROM EMP WHERE EMPNO = 7839;DBMS_OUTPUT.PUT_LINE(V_EMP.ENAME || V_EMP.SAL);
​
END;
​

如果有一个表,有100个字段,那么你程序如果要使用这100字段的话,如果你使用引用型变量一个个声明,会特别麻烦,记录型便令可以方便的解决这个问题

错误的时候:

  1. 记录型变量只能存储一个完整行数据

⭐️1.4、流程控制

1.4.1、条件分支

语法:

beginif 条件1 then 执行1elsif 条件2 then 执行2else 执行3end if;end;

注意关键字:ELSIF

示例:判断emp表中记录是否超过20条,10~20之间,或者10条以下

-- 判断emp表中记录是否超过20条,10~20之间,或者10条以下
​
DECLARE
​-- 声明变量接收emp中的数量V_COUNT INTEGER;BEGINSELECT COUNT(*) INTO V_COUNT FROM EMP;IF V_COUNT > 20THENDBMS_OUTPUT.PUT_LINE(20);ELSIF V_COUNT >= 10THENDBMS_OUTPUT.PUT_LINE(10);ELSEDBMS_OUTPUT.PUT_LINE(30);END IF;
​
​
END;
​

1.4.2、循环

在Oralce中有三种循环方式,以下介绍其中一种:loop循环。其他两种,源码放出来,大家仁者见仁智者见智。

语法:

exit中文意思出口

beginloopexit when 退出循环条件end loop;
end;

示例:打印数字1-10

loop循环

-- 打印数字1-10
​
DECLARE
​-- 声明循环变量并赋初始值V_NUM NUMBER := 1;
​
BEGINLOOPDBMS_OUTPUT.PUT_LINE(V_NUM);EXIT WHEN V_NUM = 10;-- 循环变量自增v_num := v_num + 1;END LOOP;
​
END;
​
--------------- 输出语句在后 判断条件是变量 > 10
​
-- 打印数字1-10
​
DECLARE
​-- 声明循环变量并赋初始值V_NUM NUMBER := 1;
​
BEGINLOOPEXIT WHEN V_NUM > 10;DBMS_OUTPUT.PUT_LINE(V_NUM);-- 循环变量自增v_num := v_num + 1;END LOOP;
​
END;
​
​
​
​

while循环

语法:

beginwhile 循环条件 loopend loop;
end;

/*while循环*/
​
​
declarev_num number:=1;
beginwhile v_num<10 loopdbms_output.put_line(v_num);v_num:=v_num+1;end loop;
end;
​
​

for循环

​
declarev_num number:=1;
beginfor  v_num in 1..10 loopdbms_output.put_line(v_num);end loop;
end;
​

🏆二、游标

⭐️2.1、什么是游标

用于临时存储一个查询返回的多行数据(结果集,类似于Java的jdbc连接返回的ResultSet集合),通过遍历游标,可以逐行访问处理该结果集的数据。

游标的使用方式:声明——打开——获取——关闭

⭐️2.2、语法

游标声明:CURSOR 游标名[(参数列表)] is 查询语句;
游标的打开:open 游标名;
游标的取值:FETCH 游标名 into 变量列表;
游标的关闭:CLOSE 游标名;

⭐️2.3、游标的属性

游标的属性返回值类型说明
%ROWCOUNT整型获FETCH语句返回的数据行数
%FOUND布尔型最近的FETCH语句返回一行数据则为真,否则为假
%NOTFOUND布尔型与%FOUND属性返回值相反
%ISOPEN布尔型游标已经打开时值为真,否则为假

其中%NOTFOUND是在游标中找不到元素的时候返回TRUE,通常用来判断退出循环

⭐️2.4、创建和使用

示例:使用游标查询emp表中所有员工的姓名和工资,并将其依次打印出来。

-- 使用游标查询emp表中所有员工的姓名和工资,并将其依次打印出来。 
DECLARECURSOR C_EMP ISSELECT ENAME, SAL FROM EMP;
​-- 声明变量用来接收游标中的元素V_ENAME  EMP.ENAME%TYPE;V_SALARY EMP.SAL%TYPE;
BEGIN-- 打开游标OPEN C_EMP;-- 游标的取值LOOPFETCH C_EMPINTO V_ENAME, V_SALARY;-- 通过%NOTFOUND判断是否有值,有值打印,没有则退出循环EXIT WHEN C_EMP%NOTFOUND;--#PLS-00225: 子程序或游标 'ELE' 引用超出范围--错误sql-dbms_output.put_line(c_emp.v_ename || c_emp.v_salary);DBMS_OUTPUT.PUT_LINE(V_ENAME || V_SALARY);END LOOP;-- 关闭游标CLOSE C_EMP;
​
END;
​

⭐️2.5、带参数的游标

示例:使用游标查询并打印某部门的员工的姓名和薪资,部门编号为运行时动手输入

-- 使用游标查询并打印某部门的员工的姓名和薪资,部门编号为运行时动手输入
DECLARE-- 1、游标声明;CURSOR C_EMP(V_DEPTNO EMP.DEPTNO%TYPE) ISSELECT ENAME, SAL FROM EMP WHERE DEPTNO = V_DEPTNO;
​-- 1.1声变量接收游标的值V_ENAME  EMP.ENAME%TYPE;V_SALARY EMP.SAL%TYPE;
BEGIN-- 2、游标打开OPEN C_EMP(10);-- 4、游标取值-- 5、遍历游标LOOPFETCH C_EMPINTO V_ENAME, V_SALARY;EXIT WHEN C_EMP%NOTFOUND;DBMS_OUTPUT.PUT_LINE(V_ENAME);END LOOP;-- 3、游标关闭CLOSE C_EMP;
​
END;
​

注意%NOTFOUND属性默认值为FALSE,所以在循环中要注意判断条件的位置,

  1. 如果先判断在FETCH就会导致最后一条记录的值被打印两次(默认多循环一次)

  2. 如果判断在输出后,也会导致最后一个记录的值被打印两次

如图

🏆三、存储过程

⭐️3.1、概念作用

  1. 之前我们编写的PLSQL程序可以进行表的操作,判断。循环逻辑处理的工作,但是无法重复调用。

  2. 可以理解之前的代码全部编写在了main方法中,是匿名程序,Java可以通过封装对象和方法对象来解决问题、PLSQL是将一个个PLSQL的业务处理过程存储起来进行复用,这些被存储起来的PLSQL称之为存储过程。

    存储过程作用:

  3. 在开发程序中,为了一个特定的业务功能,会向数据库进行多次连接关闭(连接和关闭时很耗费资源的),需要对数据库进行多次I/O读写,性能比较低。如果把这些业务放到PLSQL只不过,在应用程序中只需要调用PLSQL就可以做到连接关闭一次数据库就可以实现我们的业务,可以

  4. Oracle官方给的建议:能够让数据库操作的不要放在程序中。在数据库张红实现基本上不会出现错误,在程序中操作可能会存在错误.(如果在数据库中操作数据,可以有一定的日志恢复功能)

⭐️3.2、语法

create or replace procedure 过程名称(参数列表) is
beigin
end[过程名称];

根据参数的类型,我们将其分为3类讲解:

  • 不带参数的

  • 带输入参数的

  • 带输入输出参数(返回值)的

CREATE OR REPLACE PROCEDURE P_HELLO as
BEGINDBMS_OUTPUT.PUT_LINE('1234578 world');
END P_HELLO;
​

-- 创建或者替换过程 create or replace procedure procedure_demo1 as begin dbms_output.put_line('我是存储过程'); end procedure_demo1;

调用存储过程

-- Created on 2022/10/8 by ME666 
DECLARE
​
BEGINP_HELLO;
END;
​

在SQLPLUS中显示结果的前提是需要set serveroutput on

注意:

  • is和as是可以互用的,用哪个都没有关系的

  • 过程中没有declare关键字,declare用在语句块中

⭐️3.3、输入带参数的存储过程

示例:

查询并打印某个员工(如7839号员工)的姓名和薪水-存储过程:要求,调用的时候传入员工编号,自动控制台打印。

  -- 查询并打印某个员工(如7839号员工)的姓名和薪水-- 要求,调用的时候传入员工编号,自动控制台打印。CREATE OR REPLACE PROCEDURE P_QUERYNAMEANDSAL(IN_EMPNO IN EMP.EMPNO%TYPE) IS
​-- 声明变量接收查询结果V_ENAME  EMP.ENAME%TYPE;V_SALARY EMP.SAL%TYPE;
​
BEGIN
​-- 根据用户传递员工的编号 查询姓名和薪水SELECT ENAME, SAL INTO V_ENAME, V_SALARY FROM EMP WHERE EMPNO = IN_EMPNO;DBMS_OUTPUT.PUT_LINE('该员工的姓名是:' || V_ENAME || '薪资有:' || V_SALARY);
​
END P_QUERYNAMEANDSAL;
​

⭐️3.4、带输出参数的存储过程

示例:输入员工工号查询某个员工(7839)信息,要求,将薪水作为返回值输出,给调用的程序使用

  -- 输入员工工号查询某个员工(7839)信息,-- 要求,将薪水作为返回值输出,给调用的程序使用
​CREATE OR REPLACE PROCEDURE P_RETURNSALARY
(IN_EMPNO   IN EMP.EMPNO%TYPE,OUT_SALARY OUT EMP.SAL%TYPE
) IS
​-- 接收变量--  V_SALARY EMP.SAL%TYPE;
​
BEGINSELECT SAL INTO OUT_SALARY FROM EMP WHERE EMPNO = IN_EMPNO;-- DBMS_OUTPUT.PUT_LINE(V_SALARY);
​
END P_RETURNSALARY;
​
-- Created on 2022/10/9 by ME666 
declare V_SALARY EMP.SAL%TYPE;
beginP_ReturnSalary(7839,V_SALARY);DBMS_OUTPUT.PUT_LINE(V_SALARY);end;

⭐️3.5、Java程序调用存储过程

需求:如果一条语句无法实现结果集,比如需要多表查询,或者需要复杂逻辑查询,我们可以选择调用存储查询你的结果。

CallableStatement

通过Connect对象的prepareCall方法调用存储过程

得出结论:通过Connect对象调用prepareCall方法传递一个转义SQL语句调用存储过程,输入参数直接调用set方法传递,输出参数需要注册手,执行存储过程,通过get方法获取,参数列表的下标是从1开始的。

存储函数必须有返回值 存储过程可以没有返回值

 public static void main(String[] args) throws ClassNotFoundException, SQLException {//1、加载驱动Class.forName("oracle.jdbc.driver.OracleDriver");//2、获取连接String url = "jdbc:oracle:thin:@localhost:1521:orcl";String username = "scott";String password = "tiger";
​Connection conn = DriverManager.getConnection(url, username, password);
//        System.out.println("conn = " + conn);//测试数据库是否连接成功
​
​//3、获得语句String sql = "{call P_RETURNSALARY(?,?)}";CallableStatement call = conn.prepareCall(sql);//4、设置输出参数call.setInt(1, 7839);
​//5、注册输出参数call.registerOutParameter(2, OracleTypes.DOUBLE);
​//6、执行存储过程call.execute();
​//7、获取输出参数double sal = call.getDouble(2);System.out.println("sal = " + sal);
​//8、释放资源call.close();conn.close();
​
​}
​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_398701.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网状神经系统的典型特点,网状结构神经系统

脑干网状结构对肌紧张既有抑制作用也有加强作用。 选择A对。理由如下&#xff1a;网状结构中存在有抑制和加强肌紧张和肌运动区域&#xff0c;分别成为抑制区和易化区。抑制区位于网状结构的腹内侧部分。易化区位于网状结构的背外侧、脑桥被盖、中脑中央灰质及被盖。 &#x…

什么是RFID技

什么是RFID技术 RFID射频识别是一种非接触式的自动识别技术&#xff0c;它通过射频信号自动识别目标对象并获取相关数据&#xff0c;识别无需人工干预&#xff0c;可工作于各种恶劣环境。RFID技术可识别高速运动物体并同时识别多个标签&#xff0c;操作快捷方便。 ​​​​​…

Bootstrap——flex布局(定义弹性盒子、排列方向、内容排列、项目对齐、自身对齐、自动对等、等宽变换、自动边距、包裹、排序、对齐内容)

Bootstrap4与Bootstrap3最大的区别是Bootstrap 4使用弹性盒子来布局&#xff0c;而不是使用浮动来布局。弹性盒子也是CSS的一种新的布局模式&#xff0c;更适合响应式的设计。 布局的传统解决方案,基于盒状模型&#xff0c;依赖display属性 position属性 float属性。它对…

dif分页、排序、过滤功能

分页功能 接口中只有查询全部数据接口有时候数据量非常大&#xff0c;所以需要用到分页功能&#xff0c;在rest_framework中提供了三种分页的方法 一.PageNumberPagination 第一步&#xff1a;定义一个分页类继承PageNumberPagination from rest_framework.pagination import P…

Day02 -尚品汇-路由传递参数

围绕这个开展 1》在Header.vue里面 2》在Header.vue里面 第一种方式&#xff1a;&#xff08;字符串形式写法&#xff09; 传递params参数 3》在index.js里面 【此处用的是params参数 需要占位】 4》在Header.vue里面 【params写法】 1--4的效果图 我还想加一个传…

NTFS文件系统详解(二)MBR\EBR基本信息

NTFS文件系统详解&#xff08;二&#xff09;MBR\EBR基本信息一、MBR结构分析1. 第一个分区表项2. 第二个分区表项3. 第三个分区表项4. 第四个分区表项二、EBR结构分析1. 第一个分区表项2. 第二个分区表项2.1 第一个分区表项2.2 第二个分区表项2.3 第三个分区表项系列文章目录经…

springBoot实验填报系统

摘要 国内教育行业的快速发展&#xff0c;人们为了能够更加方便地管理学生实验填报&#xff0c;实验填报系统被人们开发出来从而更好地方便管理学生实验填报&#xff0c;一个完美的实验填报系统已经成为各个学校的追求目标。 本系统利用SpringBoot技术进行开发实验填报系统是未…

asp.net旅游网站系统VS开发sqlserver数据库web结构c#编程计算机网页项目

一、源码特点 ASP.NET 旅游网站系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 asp.net旅游网站系统VS开发sqlserver数…

git基本使用方式整理

文章目录A:配置个人信息B:创建目录C:初始化仓库D:往仓库添加和提交文件E:状态查看命令F:版本回退G:对git占存区的理解H&#xff1a;管理修改I&#xff1a;撤销修改J&#xff1a;删除文件K:关联远程仓库L:仓库克隆在Git安装完成之后&#xff0c;需要配置Git连接的用户信息&#…

python与Electron联合编程记录之八(Hello Flask!)

Hello Flask&#xff01; 既然知道了Electron和Flask信息交换的原理&#xff0c;我们就可以开始进行Electron和Flask的联合编程了。   让我们紧接第三部分“Hello&#xff0c;Electron!”项目继续探索Flask的用法。 1、配置虚拟环境 由于Flask是python编写的&#xff0c;所以…

Python百日进阶-WEB开发】Day156 - 前端基础 之 BootStrap(一)

文章目录一、BootStrap的安装和使用1.1 BootStrap介绍1.2 BootStrap特点1.3 下载使用1.3.1 下载BootStrap:1.3.2 下载 jquery.js1.4 创建项目1.5 bootstrap和vue对比1.5.1 Bootstrap和vue不是一个层级的东西&#xff0c;Vue是框架&#xff0c;bootstrap是基于jQuery的组建库。1…

洛谷 T281315 掌控

PS&#xff1a;如果读过题了可以跳过题目描述直接到题解部分 提交链接&#xff1a;洛谷 T281315 掌控 题目 题目描述 公元 2044 年&#xff0c;人类进入了宇宙纪元。L 国有 nnn 个星球&#xff0c;分别编号为 111 到 nnn &#xff0c;每一星球上有一个球长。有些球长十分强大…

Ryu的安装+使用

ryu的安装 安装RYU&#xff0c;需要安装一些python的套件&#xff1a; python-eventlet python-routes python-webob python-paramiko 安装RYU主要有两种方式&#xff1a; 1、pip安装 pip install ryu git clone https://github.com/osrg/ryu.git cd ryu sudo pip install -…

【路径规划】基于matlab卡尔曼滤波、三次插值极速赛道赛车路径规划【含Matlab源码 2158期】

一、卡尔曼滤波路径追踪优化简介 割草机器人通过比对当前t时刻位置、导航方程之间偏移角度θ和偏移距离d,确定t1时刻的运动方向属于递推型路径追踪。割草机器人工作过程中受到地面起伏等环境因素影响,在采用上述追踪方法时会和预测值产生偏差,造成机器人偏离导航方程,称之为系…

数据大放送之HMA

一、前言 今天给大家带来的是空间分辨率为8米的DEM数据&#xff0c;可能有小伙伴会疑惑&#xff0c;是不是需要付费&#xff1f; 不用、不用、不用&#xff0c;完全免费。 也就是我们的HMA数据&#xff0c;全称NSIDC DAAC High Mountain Asia&#xff0c;也叫高山亚洲数据集…

Java:JSP是什么?Jakarta服务器页面介绍

Jakarta Server Pages(以前称为 JavaServer Pages)是一种 Java 标准技术&#xff0c;开发人员使用它来为 Java Web 应用程序编写动态的、数据驱动的网页。JSP 建立在 Java Servlet(又名 Jakarta Servlet)规范之上&#xff0c;是 Jakarta EE 中包含的用于持续支持和升级的 Java …

JPA的学习

JPA jpa详解 JPA是Java Persistence API的简称&#xff0c;中文名Java持久层API&#xff0c;是JDK 5.0注解或XML描述对象&#xff0d;关系表的映射关系&#xff0c;并将运行期的实体对象持久化到数据库中。 Spring Date整合jpa Spring Date pring Data是Spring的一个子项目…

超详细Redis入门教程!

一、引言 为啥需要redis?没有reids有啥问题?↓ 1.1 数据库压力过大 由于用户量增大&#xff0c;请求数量也随之增大&#xff0c;数据压力过大 1.2 数据不同步 多台服务器之间&#xff0c;数据不同步 1.3 传统锁失效 多台服务器之间的锁&#xff0c;已经不存在互斥性了 redis如…

(附源码)计算机毕业设计SSM志愿者服务平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

ArcGIS基础:要素转点、要素折点转点与面转线

1、【面、线转点】&#xff1a; 实验所用数据如下&#xff1a;点、线、面分别为&#xff1a; 可以使用【要素转点】工具&#xff0c;工具位于【要素】下&#xff0c;点击之后弹出【要素转点】对话框&#xff0c;只有一点需要注意&#xff1a;【内部】&#xff0c;右侧方框有…