【Oracle】PL/SQL语法、存储过程,触发器
一、Oracle数据类型
Orcle数据类型 | 说明 | 类比MySQL数据类型 | |
---|---|---|---|
字符型 | CHAR | 固定长度的字符类型 | CHAR |
字符型 | VARCHAR2 | 可变长度的字符类型 | VARCHAR |
字符型 | LONG | 大文本类型,最大2G | |
数值型 | NUMBER | 数值类型,整数小数都可以,number(5)表示长度5的整数,number(5,2)表示共5位,含2位小数 | INT存整数,FLOAT、DOUBLE存小数 |
日期型 | DATE | 日期时间型,精确到秒 | |
日期型 | TIMESTAMP | 精确到秒的小数点后9位 | |
二进制型 | CLOB | 存储字符,最大4G(比LONG更多) | LONGTEXT |
二进制型 | BLOB | 存储图像、声音、视频等数据,最大 4G | LONGBLOB |
二、PL/SQL
PL/SQL(Procedure Language/SQL)是Oracle对SQL语言的过程化扩展,指在SQL命令语言中增加了过程处理语句(分支、循环等)。
基本语法结构
[declare-- 声明变量
]
begin--代码逻辑
[exception--异常处理
]
end;
2.1 变量
变量声明语法:
变量名 类型(长度)
变量赋值语法:
变量名:=变量值
select into赋值语法(结果必须是一条记录,多条记录和没有记录都会报错):
select 列名 into 变量名 from 表名 where 条件
2.2 属性类型
引用型语法,某个变量的类型不预先指定,而是与查询结果相同
表名.列名%type
举例:
declare v_price number(10,2);v_usenum2 number(10,2);v_usenum t_account.usenum%type;--变量的类型与t_account.num0相同v_num0 t_account.num1%type;
beginv_price:=2.45;select usenum,num0 into v_usenum,v_num0 from t_account -- 把usenum赋给v_usenum,num0赋给v_num0where year='2012' and month='01' and owneruuid=1;v_usenum2:=round(v_usenum/1000,2);
end;
记录型语法,某个变量表示一行
表名%rowtype
举例:
declare v_price number(10,2);v_usenum2 number(10,2);v_account t_account%rowtype;--表示一行记录
beginv_price:=2.45;select * into v_account from t_account where year='2012' and month='01' and owneruuid=1;--把查出来的一行给v_accountv_usenum2:=round(v_account.usenum/1000,2);--v_account是一行记录,用.列名使用对应列的值
end;
2.3 异常
oracle中有如下两个异常:
NO_DATA_FOUND:执行select into,未返回行
TOO_MANY_ROWS:执行select into,结果集超过一行
举例:
declare v_price number(10,2);v_usenum2 number(10,2);v_account t_account%rowtype;--表示一行记录
beginv_price:=2.45;select * into v_account from t_account where year='2012' and month='01' and owneruuid=1;--把查出来的一行给v_accountv_usenum2:=round(v_account.usenum/1000,2);--v_account是一行记录,用.列名使用对应列的值
exceptionwhen NO_DATA_FOUND then DBMS_OUTPUT.putline('select into 未返回数据'); -- 这句话是打印输出,类似python中print()when TOO_MANY_ROWS thenDBMS_OUTPUT.putline('select into 返回多行数据');
end;
2.4 条件判断
基本语法1:
if 条件 then 业务逻辑 end if;
基本语法2:
if 条件 then 业务逻辑 else 业务逻辑 end if;
基本语法3:
if 条件 then 业务逻辑 elsif 条件 then 业务逻辑 else 业务逻辑 end if;
2.5 循环
无条件循环语法(重点):
loop 循环语句 end loop;
举例:
declarev_num number;
beginv_num:=1;loopv_num:=v_num+1;exit when v_num>100;--loop循环中使用exit退出循环--也可以写成:if v_num>100 then exit;end if;end loop;
end;
有条件循环语法:
while 条件 loop 循环语句 end loop;
举例:
declarev_num number;
beginv_num:=1;while v_num<=100loopv_num:=v_num+1;end loop;
end;
for循环语法(重点):
for 变量 in 起始值..终止值 loop 循环语句 end loop;
举例:
beginfor v_num in 1..100 --for循环v_num自动声明,不用声明,是局部变量,只能在loop和end loop中间使用loopDBMS_OUTPUT.putline(v_num);end loop;
end;
2.6 游标
游标存放SQL语句的执行结果,可以理解成结果集,可以对其进行逐行处理。
声明游标语法:
cursor 游标名称 is SQL语句;
使用游标语法:
open 游标名称
loopfetch 游标名称 into 变量exit when 游标名称%notfound
end loop;
close 游标名称
普通游标使用举例:
declarecursor cur_pricetable is select * from t_pricetable where owertypeid = 100;--声明游标v_pricetable t_pricetable%rowtype;
beginopen cur_pricetable;--打开游标loopfetch cur_pricetable into v_pricetable;--提取游标exit when cur_pricetable%notfound;--退出循环游标DBMS_OUTPUT.putline(v_pricetable.price);--打印每一条记录的priceend loop;close cur_pricetable;--关闭游标
end;
带参数游标使用举例:
declarecursor cur_pricetable(v_ownertype number) is select * from t_pricetable where owertypeid = v_ownertype;--声明带参数的游标v_pricetable t_pricetable%rowtype;
beginopen cur_pricetable(100);--打开游标,传入参数100loopfetch cur_pricetable into v_pricetable;--提取游标exit when cur_pricetable%notfound;--退出循环游标DBMS_OUTPUT.putline(v_pricetable.price);--打印每一条记录的priceend loop;close cur_pricetable;--关闭游标
end;
for循环使用游标举例:
自动打开、关闭游标,不用声明变量,也不用fetch,可以直接使用
declarecursor cur_pricetable(v_ownertype number) is select * from t_pricetable where owertypeid = v_ownertype;--声明带参数的游标
beginfor v_pricetable in cur_pricetable(100) --for循环使用游标,变量不需要声明loopDBMS_OUTPUT.putline(v_pricetable.price);--打印每一条记录的priceend loop;
end;
三、存储函数
存储函数也称为自定义函数,接受一个或多个参数,返回一个结果。
函数中使用PL/SQL进行逻辑处理
存储函数创建语法:
语法is的后面与PL/SQL语法的declare后面是一样的
create [or replace] function 函数名称
(参数名称 参数类型,参数名称 参数类型, ...) -- 这里只写参数类型,不写长度
return 结果变量数据类型 -- 指定返回值的参数类型,不写长度
is -- 声明变量
begin-- 代码逻辑return 结果变量;
[exception-- 异常处理
]
end;
举例:
create or replace function fn_getaddress
(v_id number) -- 函数的参数是number类型
return varchar2 -- 函数的返回值是varchar2类型
is v_name varchar2(30);
begin--根据传入的v_id查询name,并返回nameselect name into v_name from t_address where id=v_id;return v_name;
end;-- 调用函数查询id=3的地址
select fn_getaddress(3) from dual;
-- 调用函数查询addressid对应的地址,不用再进行表关联
select id,name,fn_getaddress(addressid) from t_owners;
四、存储过程
存储函数和存储过程的区别:
- 存储函数只能返回一个值,存储过程可以传出多个值(返回多个值)
- 存储函数可以直接在select语句中使用,而存储过程不能
- 存储函数一般封装一个查询结果,存储过程一般封装一段事务代码
存储过程创建语法:
相比存储函数,把function换成了procedure,且没有了返回值
create [or replace] procedure 存储过程名称
(参数名称 参数类型,参数名称 参数类型, ...) -- 这里只写参数类型,不写长度,参数可以传入,也可以传出
is-- 声明变量
begin-- 代码逻辑
[exception-- 异常处理
]
end;
过程参数的三种模式:
IN 传入参数(默认)
OUT 传出参数,主要用于返回程序运行结果
IN OUT 传入传出参数
不带传出参数的存储过程举例:
create or replace procedure pro_students_add
(
v_id number,
v_name varchar2
)
is
begin insert into t_students values(v_id,v_name);commit;
end;-- 调用存储过程
call pro_students_add(10,"啦啦啦");
带传出参数的存储过程举例:
create or replace procedure pro_students_add
(
v_id number,
v_name varchar2,
v_stuid out number --声明一个传出参数
)
is
begin insert into t_students values(v_id,v_name);commit;-- 对传出参数赋值select id into v_stuid from t_students where id = v_id;
end;-- 调用传出参数的存储过程
declarev_stuid number; -- 声明一个变量,用来接收存储过程的传出参数
beginpro_students_add(10,"啦啦啦",v_stuid); -- 执行完该语句后,v_stuid就有值了,后面可以直接用DBMS_OUTPUT.putline(v_stuid);
end;
五、触发器
触发器是基于某一张表的增删改操作的,在对应的增删改操作执行之前/之后,执行一段PL/SQL代码
触发器分类:
前置触发器,在对应语句之前执行
后置触发器,在对应语句之后执行
行级触发器,每操作一条记录就执行一次触发器(一般都是行级触发器)
语句级触发器,不管操作多少条记录,一个SQL语句只对应执行一次触发器
创建触发器语法:
create [or replace] trigger 触发器名before|after[delete][[or] insert][[or] update [of 列名]]on 表名[for each row][when(条件)] -- for each row表名该触发器是行级触发器
declare
beginPL/SQL块
end;
触发器中:old和:new所代表的值:
触发语句 | :old | :new |
---|---|---|
Insert | 所有字段都是空(null) | 将要插入的数据 |
update | 更新前该行的值 | 更新后该行的值 |
delete | 删除以前该行的值 | 所有字段都是空(null) |
后置触发器举例:
-- 创建日志表,记录业务名称修改前和修改后的值
create table t_owners_log(
updatetime date,
ownerid number,
oldname varchar2(30),
newname varchar2(30)
);create or replace trigger tri_owners_log
after
update of name
on t_owners -- 当t_owners.name被update之后触发该触发器
for each row -- 行级触发器
declarebegininsert into t_owners_log values(sysdate,:new.id,:old.name,:new.name);\-- 注意触发器里不用commit,会自动commit,如果是存储过程则需要commit
end;
六、视图、物化视图、序列、同义词
视图: 一段查询的SQL语句,创建成一张视图,可以把这个视图当表来用,视图不存储数据,修改视图的内容会修改视图对应的基表
物化视图: 一段查询的SQL语句,创建成一张物化视图,会存储数据,修改物化视图不影响基表
序列: Oracle中没有自增主键,所以要用序列实现获取一个自增/自减的数据,序列.nextval获取下一个值,序列.currval返回序列的当前值
同义词: 可以理解为别名,公有同义词所有用户都能使用,私有同义词只能这个用户使用
Oracle结构:
一个Oracle只有一个数据库,一个数据库下有多个表空间
一个表空间下有多个用户,每个用户创建的表都自动在对应的表空间下
相关文章:
【Oracle】PL/SQL语法、存储过程,触发器
一、Oracle数据类型 Orcle数据类型说明类比MySQL数据类型字符型CHAR固定长度的字符类型CHAR字符型VARCHAR2可变长度的字符类型VARCHAR字符型LONG大文本类型,最大2G数值型NUMBER数值类型,整数小数都可以,number(5)表示长度5的整数,…...

2020年第九届数学建模国际赛小美赛C题亚马逊野火解题全过程文档及程序
2020年第九届数学建模国际赛小美赛 C题 亚马逊野火 原题再现: 野火是指发生在乡村或荒野地区的可燃植被中的任何不受控制的火灾。这样的环境过程对人类生活有着重大的影响。因此,对这一现象进行建模,特别是对其空间发生和扩展进行建模&…...

保姆级 Keras 实现 YOLO v3 三
保姆级 Keras 实现 YOLO v3 三 一. 分配 anchor box二. 正负样本匹配规则三. 为每一个 anchor box 打标签3.1 anchor box 长什么样?3.2 每一个 anchor box 标签需要填充的信息有哪些?3.3 ( Δ x , Δ y , Δ w , Δ h ) (\Delta x, \Delta y, \Delta w, \Delta h) (Δx,Δy,…...

HPM6750系列--第十篇 时钟系统
一、目的 上一篇中《HPM6750系列--第九篇 GPIO详解(基本操作)》我们讲解了HPM6750 GPIO相关内容,再进一步讲解其他外设功能之前,我们有必要先讲解一下时钟系统。 时钟可以说是微控制器系统中的心脏,外设必须依赖时钟才…...

【简单总结】中断类型号 中断向量 中断入口地址
通过中断类型号可以计算出中断向量的地址。 然后根据该地址可以在中断向量表中取出中断服务程序的入口地址(中断向量)。 而中断向量就是中断服务程序入口地址。 做个不严谨的图: 1:通过中断类型号找到中断向量 2:通…...
【Python百宝箱】从传感器到云端:深度解析Python在物联网中的多面应用
迈向智能未来:Python与物联网生态系统的完美融合 前言 随着物联网技术的不断发展,Python作为一种灵活且强大的编程语言,逐渐成为物联网开发的重要工具之一。本文将深入探讨物联网领域中常用的Python库和框架,涵盖了从轻量级通信…...
weston 1: 编译与运行傻瓜教程(补充)
系统kubuntu23.10 git clone https://gitlab.freedesktop.org/wayland/wayland.git 86588fbdebe7f6ac9363d98f524e4ae14bd4b019 meson build/ --prefix$WLD ninja -C build/ install git clone https://gitlab.freedesktop.org/wayland/wayland-protocols.git c4f559866f13…...

微服务保护--线程隔离(舱壁模式)
一、线程隔离的实现方式 线程隔离有两种方式实现: 线程池隔离 信号量隔离(Sentinel默认采用) 如图: 线程池隔离:给每个服务调用业务分配一个线程池,利用线程池本身实现隔离效果 信号量隔离:…...

集群监控Zabbix和Prometheus
文章目录 一、Zabbix入门概述1、Zabbix概述2、Zabbix 基础架构3、Zabbix部署3.1 前提环境准备3.2 安装Zabbix3.3 配置Zabbix3.4 启动停止Zabbix 二、Zabbix的使用与集成1、Zabbix常用术语2、Zabbix实战2.1 创建Host2.2 创建监控项(Items)2.3 创建触发器&…...
K8S(七)—污点、容忍
目录 污点、容忍污点(Taints):容忍(Tolerations):如何一起使用污点和容忍:操作符(Equal、Exists)例子基于污点的驱逐基于节点状态添加污点 污点、容忍 官网地址…...
新视野大学英语1 词组 12.17
embarrassment和awkwardness的区别以及各自的组词。 "Embarrassment" 和 "awkwardness" 都可以用来描述一种尴尬或不舒服的感觉,但它们有一些微妙的区别。 "Embarrassment" 指的是由于尴尬、困窘或难堪的情况而产生的感觉。 这种感觉…...
springboot实战项目之使用AOP技术实现各种角色的鉴权功能
前言 项目开发需求,会员有不同的角色,不同的角色被赋予不同的权限,这就需要对会员的操作进行鉴权处理。 方案 采用aop,可实现满足这种需求,创建匿名类。对外提供接口的时候都会拦截,这种会有弊端&#x…...

华为配置基本QinQ示例
组网需求 如图1所示,网络中有两个企业,企业1有两个分支,企业2有两个分支。这两个企业的各办公地的企业网都分别和运营商网络中的SwitchA和SwitchB相连,且公网中存在其它厂商设备,其外层VLAN Tag的TPID值为0x9100。 现…...
【漏洞复现】系列集合
该篇文章仅供学习网络安全技术参考研究使用,请勿使用相关技术做违法操作 Apache Apache_HTTPD_未知后缀名解析Apache_HTTPD_换行解析(CVE-2017-15715)Apache_HTTPD_多后缀解析Apache_HTTP_2.4.50_路径穿越(CVE-2021-42013)Apache_HTTP_2.4.49_路径穿越(CVE-2021-41…...

TCP报文头(首部)详解
本篇文章基于 RFC 9293: Transmission Control Protocol (TCP) 对TCP报头进行讲解,部分内容会与旧版本有些许区别。 TCP协议传输的数据单元是报文段,一个报文段由TCP首部(报文头)和TCP数据两部分组成,其中TCP首部尤其重…...
第4章-第1节-初识Java的数组
1、数组 属于Java内存层面的一款容器(crud操作)。 概念: 内存中的一块存储区域(空间),内部有一组连续的小区域(元素空间),有数据类型的限定,可以存入一组匹配类型的数据,并且根据需要可以改动元素空间中的数据内…...

大数据技术10:Flink从入门到精通
导语:前期入门Flink时,可以直接编写通过idea编写Flink程序,然后直接运行main方法,无需搭建环境。我碰到许多初次接触Flink的同学,被各种环境搭建、提交作业、复杂概念给劝退了。前期最好的入门方式就是直接上手写代码&…...

IDEA中工具条中的debug按钮不能用了显示灰色
IDEA中工具条中的debug按钮不能用了显示灰色 1. 问题描述 IDEA上的DEBUG按钮突然变成了灰色: 2. 解决办法 一通搜索,终于找到解决办法 点击 File -> Project Structure如下图操作 3. 重启,解决 4. 参考 https://www.cnblogs.com…...

【MySQL内置函数】
目录: 前言一、日期函数获取日期获取时间获取时间戳在日期上增加时间在日期上减去时间计算两个日期相差多少天当前时间案例:留言板 二、字符串函数查看字符串字符集字符串连接查找字符串大小写转换子串提取字符串长度字符串替换字符串比较消除左右空格案…...

C++相关闲碎记录(14)
1、数值算法 (1)运算后产生结果accumulate() #include "algostuff.hpp"using namespace std;int main() {vector<int> coll;INSERT_ELEMENTS(coll, 1, 9);PRINT_ELEMENTS(coll);cout << "sum: " << accumulate(…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...

FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)
错误一:yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因,后面把yaml.safe_dump直接替换成yaml.dump,确实能保存,但出现乱码: 放弃yaml.dump,又切…...