【Oracle】Oracle编程PLSQL

Oracle编程

一、PL/SQL

1、PL/SQL概述

PL/SQL(Procedure Language/SQL)是 Oracle 对 sql 语言的过程化扩展,使 SQL 语言具有过程处理能力。

基本语法结构

[declare -- 声明变量
]begin-- 代码逻辑 [exception-- 异常处理
]end;
2、变量
1)变量的声明与赋值
-- 声明变量
变量名 类型(长度);-- 变量赋值
变量名:=变量值;
2)直接赋值

声明变量水费单价、水费字数、吨数、金额。

对水费单价、字数、进行赋值 。吨数根据水费字数换算,规则为水费字数除以

1000,并且四舍五入,保留两位小数。计算金额,金额 = 单价 * 吨数。

输出:单价、数量和金额。

declarev_price number(10,2);	-- 水费单价v_usenum number; 		-- 水费字数v_usenum2 number(10,2);	-- 吨数v_money number(10,2);	-- 金额 
begin-- 变量赋值v_price:=2.45;v_usenum:=8012;-- 字数换算为吨数v_usenum2:= round( v_usenum/1000,2 );-- 计算金额v_money:=round(v_price*v_usenum2,2);-- 文字的输出dbms_output.put_line('金额:'||v_money); 
end;
2)select into 赋值
-- select into 语法
select 列名 into 变量名 from 表名 where 条件

select into 结果必须是一条记录 ,有多条记录和没有记录都会报错

declarev_price number(10,2);	-- 单价v_usenum number;		-- 水费字数v_num0 number;			-- 上月字数v_num1 number;			-- 本月字数v_usenum2 number(10,2);	-- 使用吨数v_money number(10,2);	-- 水费金额
begin-- 对单价进行赋值v_price:=3.45;-- select into赋值select usenum,num0,num1 into v_usenum,V_num0,V_num1 from T_ACCOUNT where year='2012' and month='01' and owneruuid=1;-- 字数换算v_usenum2:= round(v_usenum/1000,2);-- 计算金额v_money:=v_price*v_usenum2;-- 文字的输出DBMS_OUTPUT.put_line(''金额:'||v_money||'上月字数:'||v_num0||'本月字数'||v_num1);
end;
3、属性类型
1)%TYPE 引用型

引用某表某的字段类型

对于不知道表内类型的数据,可以直接获取表内列的类型

declarev_price number(10,2);				-- 单价v_usenum T_ACCOUNT.USENUM%TYPE;		-- 水费字数v_num0  T_ACCOUNT.NUM0%TYPE;		-- 上月字数v_num1 T_ACCOUNT.NUM1%TYPE;			-- 本月字数v_usenum2 number(10,2);				-- 使用吨数v_money number(10,2);				-- 水费金额
2)%ROWTYPE 记录型

标识某个表的记录类型

一个记录型代表一行数据,类似java编程的实体类

declarev_price number(10,2);			-- 单价v_account T_ACCOUNT%ROWTYPE;	-- 台账行的记录型v_usenum2 number(10,2);			-- 使用吨数v_money number(10,2);			-- 水费金额
begin-- 对单价进行赋值v_price:=3.45;-- select into赋值select * into v_account from T_ACCOUNT where year='2012' and month='01' and owneruuid=1;-- 使用吨数v_usenum2:= round(v_account.usenum/1000,2);-- 计算金额v_money:=v_price*v_usenum2;-- 文字的输出  DBMS_OUTPUT.put_line('金额:'||v_money);
end;
4、异常(例外)

发生异常后,语句将停止执行,控制权转移到 PL/SQL 块的异常处理部分

  • 预定义异常:Oracle预先定义的异常
    • NO_DATA_FOUND:使用 select into 未返回行
    • TOO_MANY_ROWS:执行 select into 时,结果集超过一行
  • 用户定义异常:用户定义异常,通过 RAISE 语句显式引发
-- 异常语法结构exceptionwhen 异常类型 then异常处理逻辑
declarev_price number(10,2);			-- 水费单价v_usenum T_ACCOUNT.USENUM%type; -- 水费字数v_usenum2 number(10,3);			-- 吨数v_money number(10,2);			-- 金额 begin-- 水费单价v_price:=2.45;-- select into赋值select usenum into v_usenum from T_ACCOUNTwhere owneruuid=1 and year='2012' and month='01';-- 字数换算为吨数v_usenum2:= round( v_usenum/1000,3);-- 计算金额v_money:=round(v_price*v_usenum2,2);-- 信息输出dbms_output.put_line('金额:'||v_money);-- 异常处理
exceptionwhen NO_DATA_FOUND thendbms_output.put_line('未找到数据');when TOO_MANY_ROWS thendbms_output.put_line('查询条件有误,返回多条信息');
end;
5、条件判断
-- 1、if
if 条件 then代码;
end if;-- 2、if else
if 条件 then代码;
else代码;
end if;-- 3、if elif eles
if 条件 then代码;
elsif 条件 then代码;
else代码;
end if;

设置三个等级的水费。 5 吨以下 2.45 元/吨,5 吨到 10 吨部分 3.45 元/吨,超过 10 吨部分 4.45 元/吨

根据使用水费的量来计算阶梯水费。

declarev_price1 number(10,2);		-- 不足 5 吨的单价v_price2 number(10,2);		-- 超过 5 吨不足 10 吨单价v_price3 number(10,2);		-- 超过 10 吨单价v_account T_ACCOUNT%ROWTYPE;-- 记录型v_usenum2 number(10,2);		-- 使用吨数v_money number(10,2);		-- 水费金额
begin-- 单价赋值v_price1:=2.45;v_price2:=3.45;v_price3:=4.45;-- select into赋值select * into v_account from T_ACCOUNT where year='2012' and month='01' and owneruuid=1;-- 使用吨数v_usenum2:= round(v_account.usenum/1000,2);-- 计算金额(阶梯水费)-- 第一个阶梯if v_usenum2<=5 thenv_money:=v_price1*v_usenum2;-- 第二个阶梯elsif v_usenum2>5 and v_usenum2<=10 then v_money:=v_price1*5+v_price2*(v_usenum2-5); -- 第三个阶梯elsev_money:=v_price1*5+v_price2*5+v_price3*(v_usenum2-10);end if;-- 信息输出DBMS_OUTPUT.put_line('金额:'||v_money);-- 异常处理
exceptionwhen NO_DATA_FOUND thenDBMS_OUTPUT.put_line('没有找到数据');when TOO_MANY_ROWS thenDBMS_OUTPUT.put_line('返回的数据有多行');
end;
6、循环
1)loop无条件循环
loop代码exit when 退出条件;
end loop;
-- 输出1至100
declarev_num number:=1;
begin loopdbms_output.put_line(v_num);v_num:=v_num+1;exit when v_num>100;end loop; 
end;
2)while条件循环
while 条件
loop代码
end loop;
-- 输出1至100
declarev_num number:=1;
begin while v_num<=100loopdbms_output.put_line(v_num);v_num:=v_num+1;end loop; 
end;
3)for循环
for 变量 in 起始值 .. 终止值
loop代码
end loop;
-- 输出1至100
beginfor v_num in 1 .. 100loopdbms_output.put_line(v_num); end loop;
end;
7、游标
1)游标概述

存放 SQL 语句执行的结果集

2)游标的语法
-- 声明游标
cursor 游标名称 is SQL语句;-- 使用游标
open 游标名称
loopfetch 游标名称 into 变量;exit when 游标名称%notfound;
end loop;
close 游标名称

打印业主类型为 1 的价格表

declare-- 价格的行对象v_pricetable T_PRICETABLE%rowtype;-- 定义游标cursor cur_pricetable is select * from T_PRICETABLE where ownertypeid=1;
begin-- 打开游标open cur_pricetable;loop-- 提取游标到变量fetch cur_pricetable into v_pricetable;-- 当游标到最后一行下面退出循环exit when cur_pricetable%notfound;-- 打印数据dbms_output.put_line('价格:'||v_pricetable.price); end loop;-- 关闭游标close cur_pricetable;
end ;
3)带参数的游标

条件值有可能是在运行时才能决定的

类似于java的传参

declare-- 价格的行对象v_pricetable T_PRICETABLE%rowtype;-- 定义游标cursor cur_pricetable(v_ownertype number) is select * from T_PRICETABLE where ownertypeid=v_ownertype;
begin-- 打开游标open cur_pricetable(1);loop-- 提取游标到变量fetch cur_pricetable into v_pricetable;-- 当游标到最后一行下面退出循环exit when cur_pricetable%notfound;-- 打印数据dbms_output.put_line('价格:'||v_pricetable.price); end loop;-- 关闭游标close cur_pricetable;
end ;
4)for 循环提取游标值
declare-- 定义游标cursor cur_pricetable(v_ownertypeid number) is select * from T_PRICETABLE where ownertypeid=v_ownertypeid;
begin-- for循环for v_pricetable in cur_pricetable(3)loop dbms_output.put_line('价格:'||v_pricetable.price); end loop; 
end ;

二、存储函数

1、存储函数概述

存储函数又称为自定义函数。可以接收一个或多个参数,返回一个结果。

2、存储函数语法结构
create [ or replace ] function 函数名称
(参数名称 参数类型, 参数名称 参数类型, ...)
return 结果变量数据类型
is变量声明部分;
begin逻辑部分;return 结果变量;
[exception 异常处理部分]
end;
3、案例

创建存储函数,根据地址 ID 查询地址名称

create function fn_getaddress(v_id number) 
return varchar2
isv_name varchar2(30);
beginselect name into v_name from t_address where id=v_id;return v_name;
end;
-- 测试函数
select fn_getaddress(3) from dual-- 函数在子查询的应用
select id 编号,name 业主名称,fn_getaddress(addressid) 地址 from t_owners

三、存储过程

1、存储过程概述

存储过程没有return,但是可以通过传出函数,传出多个返回值

应用程序可以调用存储过程,执行相应的逻辑,对业务逻辑的封装。

与MVC框架的思想冲突

效率比MVC框架高

2、存储过程语法结构
create [ or replace ] procedure 存储过程名称
(参数名 类型, 参数名 类型, 参数名 类型)
is|as变量声明部分;
begin逻辑部分;
[exception 异常处理部分;]
end;

参数只指定类型,不指定长度

过程参数的三种模式:

  • IN :传入参数(默认)
  • OUT :传出参数 ,主要用于返回程序运行结果
  • IN OUT :传入传出参数
3、案例
1)不带传出参数的存储过程
-- 创建
create or replace procedure pro_owners_add 
(v_name varchar2,v_addressid number,v_housenumber varchar2, v_watermeter varchar2,v_type number
)
is
begininsert into T_OWNERS values( seq_owners.nextval,v_name,v_addressid,v_housenumber,v_watermeter,sysdate,v_type);commit;
end;-- 调用
-- 1、call
call pro_owners_add('赵伟',1,'999-3','132-7',1);
-- 2、begin end
beginpro_owners_add('赵伟',1,'999-3','132-7',1);
end;
// JDBC 调用存储过程
public static void add(Owners owners){java.sql.Connection conn = null;java.sql.CallableStatement stmt = null;try {conn = BaseDao.getConnection();stmt = conn.prepareCall("{call pro_owners_add(?,?,?,?,?)}");stmt.setString(1, owners.getName());stmt.setLong(2, owners.getAddressid());stmt.setString(3, owners.getHousenumber());stmt.setString(4, owners.getWatermeter());stmt.setLong(5, owners.getOwnertypeid());stmt.execute();} catch (SQLException e) {e.printStackTrace();} finally {BaseDao.closeAll(null, stmt, conn);}
}
2)带传出参数的存储过程
-- 创建
create or replace procedure pro_owners_add 
(v_name varchar2,v_addressid number,v_housenumber varchar2, v_watermeter varchar2,v_type number,v_id out number -- 传出参数
)
is 
beginselect seq_owners.nextval into v_id from dual;insert into T_OWNERS values(v_id,v_name,v_addressid,v_housenumber,v_watermeter,sysdate,v_type);commit;
end;-- 调用
declarev_id number;
beginpro_owners_add('王旺旺',1,'922-3','133-7',1,v_id);DBMS_OUTPUT.put_line('增加成功,ID:'||v_id);
end;
// JDBC 调用存储过程
public static long add(Owners owners) {long id = 0;java.sql.Connection conn = null;java.sql.CallableStatement stmt = null;try {conn = BaseDao.getConnection();stmt = conn.prepareCall("{call pro_owners_add(?, ?,?,?,?,?)} ");stmt.setString(1, owners.getName());stmt.setLong(2, owners.getAddressid());stmt.setString(3, owners.getHousenumber());stmt.setString(4, owners.getWatermeter());stmt.setLong(5, owners.getOwnertypeid());// 册传出参数类型:表明第六个参数是传出参数stmt.registerOutParameter(6, OracleTypes.NUMBER);// 执行stmt.execute();// 执行后传出参数id = stmt.getLong(6);} catch (SQLException e) {e.printStackTrace();} finally {BaseDao.closeAll(null, stmt, conn);}return id;
}

四、触发器

1、触发器概述

触发器是一个与表相关联的、存储的PL/SQL程序。

每当一个特定的操作,Oracle自动地执行触发器中定义的语句序列。

触发器可用于

  • 数据确认:录入的合法性验证
  • 实施复杂的安全性检查
  • 做审计,跟踪表上所做的数据操作等
  • 数据的备份和同步

触发器分类

  • 前置触发器(BEFORE):sql执行前执行触发器,可以修改sql执行的值
  • 后置触发器(AFTER):sql执行后执行触发器
2、创建触发器
create [or replace] trigger 触发器名before|after[delete][[or] insert] [[or] update[of 列名]]on 表名[for each row][when(条件)]
declare变量
begin代码
end;
  • FOR EACH ROW :作用是标注此触发器是行级触发器,不标注为语句级触发器
    • 行级触发器:每影响一行触发一次
    • 语句级触发器:每个语句只触发一次

在触发器中触发语句与伪记录变量的值

触发语句:old(修改前的行数据):new(修改后的行数据)
insert所有字段都是空(null)将要插入的数据
update更新以前该行的值更新后的值
delete删除以前该行的值所有字段都是空(null)
3、案例
1)前置触发器

当用户输入本月累计表数后,自动计算出本月使用数

CREATE OR REPLACE TRIGGER tri_account_update_num1before UPDATE OF num1 ON t_account FOR each ROW
DECLARE
BEGIN: new.usenum :=: new.num1 -: new.num0;
END;
2)后置触发器

当用户修改了业主信息表的数据时记录修改前与修改后的值

CREATE TRIGGER tri_owners_logafterUPDATE OF nameON t_ownersFOR each ROW
DECLARE
BEGININSERT INTO t_owners_log VALUES(SYSDATE,: old.id,: old.name,: new.name);
END;

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

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

相关文章

Java面试之虚拟机

1、前言 本篇的面试题基于网络整理&#xff0c;和自己编辑。在不断的完善补充哦。 2、什么是虚拟机&#xff1f; Java 虚拟机&#xff0c;是一个可以执行 Java 字节码的虚拟机进程。Java 源文件被编译成能被 Java 虚拟机执行的字节码文件( .class )。 Java 被设计成允许应用程…

编译和链接(1)

目录 1. 程序的翻译环境和执行环境 2. 详解编译链接 2.1 翻译环境 2.2 编译本身也分为几个阶段&#xff1a; 2.3 运行环境 3. 预处理详解 3.1 预定义符号 3.2 #define 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 3.2.3 #define 替换规则 3.2.4 #和## 1. 程序的翻译环境和执…

怎么做手机App测试?app测试详细流程和方法介绍!

1、手机APP测试怎么做&#xff1f; 手机APP测试&#xff0c;主要针对的是android和ios两大主流操作系统&#xff0c;主要考虑的就是功能性、兼容性、稳定性、易用性&#xff08;也就是人机交互&#xff09;、性能。 手机APP测试前的准备&#xff1a; 1.使用同类型的产品&…

多语言生成式语言模型用于零样本跨语言事件论证提取(ACL2023)

1、写作动机&#xff1a; 经过预训练的生成式语言模型更好地捕捉实体之间的结构和依赖关系&#xff0c;因为模板提供了额外的声明性信息。先前工作中模板的设计是依赖于语言的&#xff0c;这使得很难将其扩展到零样本跨语言转移设置。 2、主要贡献&#xff1a; 作者提出了一…

STM32 定时器输入捕获1——初始化配置

当想检测高电平或低电平的持续时间的时候&#xff0c;就可以使用定时器输入捕获。例如示波器就是用到这个功能。这里就讲解一下定时器到底是如何输入捕获的&#xff1a; 由上图我们可以知道&#xff0c;周期 是每次连续的上升沿的时间差&#xff08;例如&#xff1a;T第二个方波…

数据分析基础

数据运营的概念及意义 数据分析的三个维度 数据总览的作用及提升方法 数据总览的作用及提升方法 数据总览的作用及提升方法小结 影响作品数据的关键因素 影响作品数据的关键因素小结 用户数据的意义与作用 用户数据分析的方法与操作 用户数据分析的方法与操作小结 数据运营小结…

最新AI绘画Midjourney绘画提示词Prompt大全

一、Midjourney绘画工具 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭…

NAND新一代接口Separate Command Address (SCA) 简介

通过NAND Flash总线传输的信号分为三种类型&#xff1a;命令&#xff08;Commands&#xff09;、地址&#xff08;Addresses&#xff09;和数据&#xff08;Data&#xff09;。这些信号利用DQ[7:0]时间分时复用技术&#xff0c;在不同的时间段分别进行传输。其中&#xff0c;数…

vcruntime140.dll已加载,但找不到入口点的处理方法分享

当遇到错误提示“vcruntime140.dll已加载&#xff0c;但找不到入口点”时&#xff0c;很多人可能会感到困惑&#xff0c;不知道如何去处理这个问题。不过没有必要紧张&#xff0c;在这里我会为大家详细解释 vcruntime140.dll 文件是什么&#xff0c;并指导大家如何高效地解决 v…

VMware workstation安装MX-23.1虚拟机并配置网络

VMware workstation安装MX-23.1虚拟机并配置网络 MX Linux是基于Debian稳定分支的面向桌面的Linux发行&#xff0c;采用Xfce作为缺省桌面&#xff0c;是一份中量级操作系统。该文档适用于在VMware workstation平台安装MX-23.1虚拟机。 1.安装准备 1.1安装平台 Windows 11 …

如何实现IOS APP被杀掉后依然可以接收到个推消息通知

背景 项目已经集成了个推SDK&#xff0c;但是在离线场景下无法收到推送消息&#xff0c;离线场景主要分2种情况&#xff0c;一种是用户将APP切换到了后台&#xff0c;一种是用户将APP杀掉了。 针对场景一&#xff1a;我们可以将APP支持后台运行&#xff0c;比如项目中使用到了…

2024年烟花爆竹经营单位安全管理人员证考试题库及烟花爆竹经营单位安全管理人员试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年烟花爆竹经营单位安全管理人员证考试题库及烟花爆竹经营单位安全管理人员试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特…