【PLSQL】PLSQL基础
文章目录
- 一:记录类型
- 1.语法
- 2.代码实例
- 二:字符转换
- 三:%TYPE和%ROWTYPE
- 1.%TYPE
- 2.%ROWTYPE
- 四:循环
- 1.LOOP
- 2.WHILE(推荐)
- 3.数字式循环
- 五:游标
- 1.游标定义及读取
- 2.游标属性
- 3.NO_DATA_FOUND和%NOTFOUND的区别
- 六:异常错误
- 1.异常处理
- 2.非预定义异常处理
- 3.用户自定义的异常处理
- 七:存储过程或函数
- 1.函数
- 函数调用过程:
- 八:包
- 1.包的创建
- 2.包的调用
- 九:触发器
- 1.触发器的组成
- 2.语法
- 3.触发器的限制
- 4.实例
- 5.创建替代(INSTEAD OF)触发器
一:记录类型
1.语法
TYPE record_type IS RECORD(column1 type,colunm2 type,… …
Variable_name record_type;
2.代码实例
declaretype test_rec is record( --test_rec记录类型l_name varchar2(30),d_id number(4));v_emp test_rec; --v_emp变量名
begin v_emp.l_name := '张三';v_emp.d_id := 1234;dbms_output.put_line(v_emp.l_name || ',' || v_emp.d_id);
end;
可以使用SELECT语句对记录变量进行赋值,只要保证记录字段与查询结果列表中的字段相匹配即可.
create table cux.employee
(last_name varchar2(20),
department_id number(4));insert into cux.employee values('李四',1235,234);declaretype test_rec is record( --test_rec记录类型l_name varchar2(30),d_id number(4));v_emp test_rec; --v_emp变量名
begin select last_name, department_id into v_empfrom cux.employeewhere employee_id = 234;dbms_output.put_line(v_emp.l_name || ', ' || v_emp.d_id);
end;
二:字符转换

三:%TYPE和%ROWTYPE
1.%TYPE
定义一个变量,其数据类型与已经定义的某个数据变量的类型相同,或者与数据库表的某个列的数据类型相同,这时可以使用%TYPE
使用%TYPE的优点:
- 所引用的数据库列的数据类型不必知道;
- 所引用的数据库列的数据类型可以实时改变.
declaretype test_rec is record(l_name cux.employee.last_name%type,d_id cux.employee.department_id%type);v_emp test_rec;
beginselect last_name,department_id into v_empfrom cux.employee where employee_id = 234;dbms_output.put_line(v_emp.l_name || ', ' || v_emp.d_id);
end;
2.%ROWTYPE

四:循环
1.LOOP
LOOP要执行的语句;EXIT WHEN<条件语句>; --条件满足,退出
END LOOPdeclareint NUMBER(2) := 0;
beginLOOPint := int + 1;dbms_output.put_line('int的当前值为:' || int);EXIT WHEN int = 10;END LOOP;
END;
2.WHILE(推荐)
WHILE<布尔表达式> LOOP要执行的语句;
END LOOP;DECLAREx NUMBER(2) := 0;
BEGINWHILE x < 10 LOOPx := x + 1;dbms_output.put_line('x的当前值为:' || x);END LOOP;
END;
3.数字式循环
FOR 循环计数器 IN[REVERSE] 下限 .. 上限 LOOP要执行的语句
END LOOP;
每循环一次,循环变量自动加1;使用关键字REVERSE,循环变量自动减1。跟在IN REVERSE后面的数字必须是从小到大的顺序,而且必须是整数,不能是变量或者表达式。可以使用EXIT退出循环。
beginFOR i in reverse 2 .. 10 LOOPDBMS_OUTPUT.PUT_LINE('i的值为' || i);END LOOP;
end;
五:游标
1.游标定义及读取
--游标FOR读取
declare cursor c_emp(dep_id number default 1236) is select last_name,employee_id epidfrom cux.employeewhere department_id = dep_id;
beginfor v_emp in c_emp loopDBMS_OUTPUT.PUT_LINE(v_emp.last_name || ', ' || v_emp.epid);end loop;
end;
2.游标属性
- %FOUND:布尔类型属性,当最近一次读记录时成功返回,则值为TRUE;
- %NOTFOUND:布尔类型属性,与%FOUND相反;
- %ISOPEN:布尔型属性,当游标已打开时返回TRUE;
- %ROWCOUNT:数字型属性,返回已从游标中读取的记录数。
3.NO_DATA_FOUND和%NOTFOUND的区别
SELECT … INTO 语句触发NO_DATA_FOUND;
当一个显示游标的WHERE子句未找到时触发%NOTFOUND;当UPATE或DELETE语句的WHERE子句未找到时触发SQL%NOTFOUND;在提取循环中要用%NOTFOUND或%FOUND来确定循环退出条件,不要用NO_DATA_FOUND。
六:异常错误

1.异常处理
EXCEPTION WHEN first_exception THEN <code to handle first exception>WHEN second_exception THEN <code to handle second exception>WHEN OTHERS THEN <code to handle others exception>
END;
异常处理可以按照任意次序排列,但OTHERS必须放在最后。
declare -- Local variables herev_empid cux.employee.employee_id%type := &v_empid;v_sal cux.employee.salary%type;
/* 预定义异常处理 */
begin-- Test statements hereselect salary into v_salfrom cux.employeewhere employee_id = v_empidfor update;if v_sal <= 3000 then update cux.employee set salary = salary+1000where employee_id = v_empid;DBMS_OUTPUT.PUT_LINE('编号为:'|| v_empid || '工资已更新');else DBMS_OUTPUT.PUT_LINE('编号为:'|| v_empid || '工资不需更新');end if;
exceptionWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('编号为:'|| v_empid || '员工不存在');WHEN TOO_MANY_ROWS THENDBMS_OUTPUT.PUT_LINE('数据行数太多,请使用游标');WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('其他错误');
end;
2.非预定义异常处理
-
在PL/SQL块定义部分定义异常情况 <异常情况> EXCEPTION
-
将其定义好的异常情况,与标准的ORACLE错误联系起来,使用PRAGMA EXCEPTION_INIT语句;
PRAGMA EXCEPTION(<异常情况>,<错误代码>);
-
在PL/SQL异常情况处理部分对异常情况做出相应处理。
3.用户自定义的异常处理
用户定义的异常错误是通过显式使用RAISE语句来触发。当引发一个异常错误时,控制就转向到EXCEPTION块异常错误部分,执行错误处理代码。
步骤:
-
在PL/SQL块的定义部分定义异常情况;
-
<异常情况> EXCEPTION
RAISE<异常情况>;
在PL/SQL块的异常情况处理部分对异常情况做出相应处理。
七:存储过程或函数
把PL/SQL程序存储在数据库中,并可以在任何地方来运行它。过程和函数的唯一区别是函数总向调用者返回数据,而过程则不返回数据。
1.函数
IN参数标记表示传递给函数的值在该函数执行中不改变;OUT标记表示一个值在函数中进行计算并通过该参数传递给调用语句;IN OUT标记表示传递给函数的值可以变化并传递给调用语句。若省略标记,则参数隐含为IN。因为函数需要一个返回值,所以RETURN包含返回结果的数据类型。
create or replace function get_salary(dep_id cux.employee.department_id%type (default 1235),emp_count out number)return numberisv_sum number;
beginselect sum(salary), count(*) into v_sum, emp_countfrom cux.employeewhere department_id = dep_id;return v_sum;
exceptionwhen no_data_found then DBMS_OUTPUT.PUT_LINE('查询的数据不存在');when others then DBMS_OUTPUT.PUT_LINE(sqlcode || '--' || sqlerrm);end;
函数调用过程:
1.位置表示法;
declarev_num number;v_sum number;
beginv_sum := get_salary(1237, v_num);DBMS_OUTPUT.PUT_LINE('1237号部门的工资总和:' || v_sum || ' 人数:' || v_num);
end;
2.名称表示法
形式参数必须和函数定义时声明的形式参数名称相同,顺序可以任意排列。
v_sum := get_salary(dep_id => 1237, emp_count => v_num);
3.混合表示法
使用位置表示法所传递的参数必须放在名称表示法所传递的参数前面。也就是说,无论函数具有多少个参数,只要其中有一个参数使用名称表示法,其后所有的参数都必须使用名称表示法。
v_sum := get_salary(1237, emp_count => v_num);
八:包
1.包的创建
create or replace package demo_pack is-- Author : 11313321-- Created : 2023/8/22 8:45:06-- Purpose : 练习测试-- Public type declarationsEmpRec cux.employee%ROWTYPE;-- Public function and procedure declarationsfunction add_emp(last_name VARCHAR2, dept_id number, emp_id NUMBER, salary number)return number;function remove_emp(emp_id number)return number;procedure query_empl(emp_id number);end demo_pack;
包主体的创建方法,它实现上面所声明的包定义:
create or replace package body demo_pack isfunction add_emp(last_name VARCHAR2, dept_id number, emp_id NUMBER, salary number)return numberisempno_remaining exception;pragma exception_init(empno_remaining, -1);begininsert into cux.employee values(last_name, dept_id, emp_id, salary,TO_DATE('2023,5,20','yyyy-mm-dd'));if sql%found thenreturn 1;end if;exceptionwhen empno_remaining then return 0;when others then return -1;end add_emp;function remove_emp(emp_id number)return numberisbegindelete from cux.employee where employee_id = emp_id;if sql%found then return 1;elsereturn 0;end if;exceptionwhen others thenreturn -1;end remove_emp;procedure query_empl(emp_id number)isbeginselect * into EmpRec from cux.employee where employee_id = emp_id;exceptionwhen no_data_found thenDBMS_OUTPUT.PUT_LINE('数据库中没有该员工');when too_many_rows thenDBMS_OUTPUT.PUT_LINE('程序运行错误!请使用游标');when others thenDBMS_OUTPUT.PUT_LINE(sqlcode || '--' || sqlerrm);end query_empl;begin-- Initializationnull;
end demo_pack;
2.包的调用
对包内共有元素的调用格式为:报名.元素名称
declarevar number;
beginvar := demo_pack.add_emp('老马', 1476, 789, 3800);if var=-1 thenDBMS_OUTPUT.PUT_LINE(sqlcode || '--' || sqlerrm);elsif var=0 thenDBMS_OUTPUT.PUT_LINE('该记录已存在');else DBMS_OUTPUT.PUT_LINE('添加记录成功');demo_pack.query_empl(789);DBMS_OUTPUT.PUT_LINE(demo_pack.EmpRec.employee_id||'--'||demo_pack.EmpRec.last_name||'--'||demo_pack.EmpRec.department_id);var := demo_pack.remove_emp(788);if var=-1 thenDBMS_OUTPUT.PUT_LINE(sqlcode || '--' || sqlerrm);elsif var=0 thenDBMS_OUTPUT.PUT_LINE('该记录不存在');elseDBMS_OUTPUT.PUT_LINE('删除记录成功');end if;end if;
end;
九:触发器
1.触发器的组成
- 触发事件:在何种情况下触发TRIGGER,例如:INSERT,UPDATE,DELETE
- 触发时间:触发之前(BEFORE)、之后(AFTER)
- 触发器本身:触发之后的目的和意图
- 触发频率:语句级(STATEMENT)触发器和行级(ROW)触发器。
- 语句级:当触发某事件时,该触发器只执行一次
- 行级:当某事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次。
- 行触发器和语句触发器的区别表现在:行触发器要求当一 个 DML 语句操做影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激 活一次触发器;而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。
2.语法
CREATE [OR REPLACE] TRIGGER trigger_name{BEFORE | AFTER}{INSERT|DELETE|UPDATE[OF column[,column...]]}ON [schema.] table_name[FOR EACH ROW][WHEN condition]trigger body;
FOR EACH ROW选项说明触发器为多行触发器。当省略FOR EACH ROW选项时,BEFORE和AFTER触发器为语句触发器,而INSTEAD OF触发器则为行触发器。
3.触发器的限制
- 触发器体内的SELECT语句只能为SELECT…INTO…结构,或者为定义游标所使用的SELECT语句。
- 触发器中不能使用数据库事务控制语句COMMIT;ROLLBACK;SAVEPOINT语句。
- 由触发器所调用的过程或函数也不能使用数据库事务控制语句。
当触发器被触发时,要使用被插入、更新或删除的记录中的列值,有时要使用操作前、后列的值
- :NEW 修饰符访问操作完成后列的值
- :OLD 修饰符访问操作完成前列的值
4.实例
--创建表
create table cux.emp_his as
select * from cux.employee
where 1 = 2;--创建触发器
create or replace trigger del_emp_triggerbefore delete on cux.employee for each row
begininsert into cux.emp_his(last_name, department_id, employee_id, salary)values(:old.last_name, :old.department_id, :old.employee_id, :old.salary);
end;
5.创建替代(INSTEAD OF)触发器
CREATE [OR REPLACE] TRIGGER trigger_name
INSTEAD OF
{INSERT | DELETE | UPDATE [OF column [, column …]]}
ON [schema.] view_name
[FOR EACH ROW ]
[WHEN condition]
trigger_body;
INSTEAD OF用于对视图的DML触发。
相关文章:
【PLSQL】PLSQL基础
文章目录 一:记录类型1.语法2.代码实例 二:字符转换三:%TYPE和%ROWTYPE1.%TYPE2.%ROWTYPE 四:循环1.LOOP2.WHILE(推荐)3.数字式循环 五:游标1.游标定义及读取2.游标属性3.NO_DATA_FOUND和%NOTFO…...
【C++笔记】C++内存管理
【C笔记】C内存管理 一、C中动态内存申请的方式二、new和delete的实现原理2.1、operator new和operator delete函数 一、C中动态内存申请的方式 在C语言中我们需要动态申请空间的时候我们通常都是用malloc函数,但是malloc函数对自定义类型是没什么问题的࿰…...
十四五双碳双控时代下的“低碳认证”
目录 前言 十四五双碳双控时代下的“低碳认证” 一、关于“低碳认证” 二、低碳认证优势 三、环境产品认证EPD 四、EPD相关运营机构 五、碳中和相关机构 六、EPD的认证流程 七、低碳产品认证认证流程和要求 八、相关机构认证证书样例 九、证书附件表 前言 通过本篇文…...
Android——基本控件(下)(十九)
1. 菜单:Menu 1.1 知识点 (1)掌握Android中菜单的使用; (2)掌握选项菜单(OptionsMenu)的使用; (3)掌握上下文菜单(ContextMenu&am…...
聚类分析 | MATLAB实现基于DBSCAD密度聚类算法可视化
聚类分析 | MATLAB实现基于LP拉普拉斯映射的聚类可视化 目录 聚类分析 | MATLAB实现基于LP拉普拉斯映射的聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于DBSCAD密度聚类算法可视化,MATLAB程序。 使用带有KD树加速的dbscan_with_kdtree函数进行…...
reactantd(12)动态表单的默认值问题
最近遇到一个需求是有一个表单可以输入各种信息,然后还需要有一个编辑功能,点击编辑的时候需要把当前数据填入到表单里面。在网上查了很多种方法,然后我的思路是使用initialValues搭配setState()使用。默认值都为空,然后点击单条数…...
无涯教程-Python机器学习 - Stochastic Gradient Boosting函数
它也称为梯度提升机。在下面的Python食谱中,我们将通过使用pima Indians糖尿病数据集上的 sklearn 的 GradientBoostingClassifier 类来创建随机梯度Boostingensemble模型进行分类。 首先,导入所需的软件包,如下所示: from pandas import read_csv from sklearn.model_select…...
SOLIDWORKS中多实体文件到装配体的转换技巧
我们在做机械等工程设计中,有时为了节省时间,需要把多实体的“零件”,直接转换为装配体,不再另外装配,这样能大大简化设计的操作时间,复杂程度。 在这里,我们首先要了解,SOLIDWORKS文…...
Transformer (Attention Is All You Need) 论文精读笔记
Transformer(Attention Is All You Need) Attention Is All You Need 参考:跟李沐学AI-Transformer论文逐段精读【论文精读】 摘要(Abstract) 首先摘要说明:目前,主流的序列转录(序列转录:给…...
Git企业开发控制理论和实操-从入门到深入(二)|Git的基本操作
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助。 高质量博客汇总https://blog.csdn.net/yu_cblog/cate…...
Positive Technologies 专家帮助修复 Western Digital 网络存储设备中的一个危险漏洞
Positive Technologies 专家帮助修复 Western Digital 网络存储设备中的一个危险漏洞 经过验证的攻击者可利用该漏洞在受攻击的设备上注入恶意软件并远程访问文件 Western Digital 感谢 Positive Technologies 专家 Nikita Abramov 发现 Western Digital NAS 固件中的一个漏洞…...
【springboot】springboot定时任务:
文章目录 一、文档:二、案例: 一、文档: 【cron表达式在线生成器】https://cron.qqe2.com/ 二、案例: EnableScheduling //开启任务调度package com.sky.task;import com.sky.entity.Orders; import com.sky.mapper.OrderMapper; …...
腾讯云学生服务器申请、学生认证入口及学生机价格表
腾讯云学生服务器申请、学生认证入口及学生机价格表,学生机申请流程,腾讯云学生服务器优惠活动:轻量应用服务器2核2G学生价30元3个月、58元6个月、112元一年,轻量应用服务器4核8G配置191.1元3个月、352.8元6个月、646.8元一年&…...
pip安装mysqlclient依赖报错 /bin/sh: 1: mysql_config: not found如何解决
报错信息: Collecting mysqlclient2.1.0Downloading https://mirrors.aliyun.com/pypi/packages/de/79/d02be3cb942afda6c99ca207858847572e38146eb73a7c4bfe3bdf154626/mysqlclient-2.1.0.tar.gz (87 kB)|███████████████████████████…...
基于paddleocr的版面分析
前处理: DocTr: Document Image Transformer for Geometric Unwarping and Illumination Correction (1)几何矫正 给定一张存在几何和光照畸变的文档图像,我们首先用一个包含六个卷积模块的特征提取器对其进行特征提取…...
网工内推 | IT网工,华为、华三认证优先,15k*13薪
01 广东善能科技发展股份有限公司 招聘岗位:IT网络工程师 职责描述: 1、负责公司项目售后技术支持工作; 2、负责项目交付实施,配置调试、运维等; 3、参加合作厂商产品技术知识培训; 4、参加合作厂商工程师…...
leetcode 739. 每日温度
2023.8.28 本题用暴力双层for循环解会超时,所以使用单调栈来解决,本质上是用空间换时间。维护一个单调递减栈,存储的是数组的下标。 代码如下: class Solution { public:vector<int> dailyTemperatures(vector<int>&…...
【活体检测模型】活体检测思路推演
ref:https://arxiv.org/pdf/1611.05431.pdf https://github.com/miraclewkf/ResNeXt-PyTorch 用分类的思想做活体检测,要求准确的分出正负样本,否则,支付宝被别人用了,问题就很严重。 大部分的商用场景还是 摇摇头、张张口&#x…...
【微服务部署】03-健康检查
文章目录 1. 探针集成实现高可用1.1 LivenessProbe1.2 ReadinessProbe1.3 StartupProbe 2. 健康检查看板2.1 组件包 1. 探针集成实现高可用 LivenessReadinessStartup 1.1 LivenessProbe 判断服务是否存活结束“非存活”状态服务根据重启策略决定是否重启服务 1.2 Readines…...
SQL注入之报错注入
文章目录 报错注入是什么?报错注入获取cms账号密码成功登录 报错注入是什么? 在注入点的判断过程中,发现数据库中SQL 语句的报错信息,会显示在页面中,因此可以利用报错信息进行注入。 报错注入的原理,就是在…...
PointPillars 架构详解
PointPillars 是自动驾驶 3D 目标检测领域里一篇里程碑式的工作,发表于 CVPR 2019,作者来自 nuTonomy。它的核心贡献是提出了一种极其简洁但高效的点云编码方式,在 KITTI benchmark 上以 62Hz 的推理速度打败了当时所有方法,包括同…...
深度学习模型边缘部署技术与优化实践
1. 深度学习模型边缘部署的技术全景在计算机视觉和自然语言处理领域,深度学习模型的边缘部署正经历着从理论到实践的深刻变革。与传统的云端部署相比,边缘部署将计算能力下沉到终端设备,实现了数据处理的本土化。这种转变不仅大幅降低了网络延…...
基于Seedream_MCP构建AI工具服务器:从协议解析到实战开发
1. 项目概述与核心价值最近在折腾AI应用开发,特别是想给大模型装上一个能“动手动脚”的插件系统时,发现了一个挺有意思的项目:skyinv/Seedream_MCP。简单来说,这是一个基于模型上下文协议的开源实现,它能让你的AI助手…...
Softether实战:用它把家里旧电脑变成公司远程访问网关,支持Win/Mac/iOS/Android全平台
利用SoftEther实现跨平台远程办公网关搭建指南 引言 在数字化办公日益普及的今天,远程访问企业内部资源已成为许多企业的刚需。传统商业解决方案往往价格昂贵且配置复杂,而基于SoftEther的开源方案则提供了一种高性价比的替代选择。本文将详细介绍如何利…...
终极指南:3秒快速预览Office文档,无需安装完整Office套件
终极指南:3秒快速预览Office文档,无需安装完整Office套件 【免费下载链接】QuickLook.Plugin.OfficeViewer Word, Excel, and PowerPoint plugin for QuickLook. 项目地址: https://gitcode.com/gh_mirrors/qu/QuickLook.Plugin.OfficeViewer 在W…...
亲测分享!优豆云免费资源助力我的小站起飞,还有惊喜优惠
大家好呀! 最近一直在捣鼓自己的个人小项目和博客,对于像我这样的新手来说,成本控制是首要考虑的问题。偶然间发现了 优豆云 这个宝藏平台 (https://www.udouyun.com),简直是为我们这些预算有限但又想练手、展示创意的朋友量身定做…...
USB端口如何管控?分享五个管控USB端口的小技巧,建议学起来
在企业数字化办公的今天,USB接口既是便利的工具,也是数据泄露的“重灾区”。U盘病毒入侵、核心资料被拷贝等风险时刻威胁着内网安全。如何科学、有效地管理这些“不安分”的接口?以下为您分享五个USB端口管控技巧,您可以根据企业的…...
教育 SaaS 供应链勒索攻击机理与闭环防御研究 —— 以 Canvas 数据泄露事件为例
摘要 2026 年 5 月,教育科技企业 Instructure 旗下 Canvas 学习管理系统遭遇 ShinyHunters 黑客组织攻击,3.65TB 数据遭窃取,波及近 9000 家教育机构、2.75 亿条用户记录,攻击者通过 Free‑for‑Teacher 环境工单相关漏洞获取初始…...
别再死记硬背MPNN公式了!用“邻居传纸条”的比喻彻底搞懂消息传递神经网络
用"班级传纸条"游戏理解消息传递神经网络 想象一下,你正坐在教室里,老师突然宣布要进行一个特殊的游戏——每个同学可以给任意一位朋友传递一张写有秘密信息的纸条。这个看似简单的游戏,恰恰揭示了人工智能领域最前沿的图神经网络(…...
【CLIP论文阅读】:基于自然语言监督的通用视觉预训练范式
论文信息 标题:Learning Transferable Visual Models From Natural Language Supervision会议:ICML 2021单位:OpenAI代码:https://github.com/OpenAI/CLIP论文:https://arxiv.org/pdf/2103.00020.pdf 一、引言&#x…...
