【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 语句的报错信息,会显示在页面中,因此可以利用报错信息进行注入。 报错注入的原理,就是在…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...