首页 > 数据库 >Oracle PL/SQL(变量-条件控制-循环控制-游标-异常)

Oracle PL/SQL(变量-条件控制-循环控制-游标-异常)

时间:2024-12-14 14:22:55浏览次数:9  
标签:END -- 游标 emp SQL Oracle rec LOOP

一、

SQL语句:

DML-数据操作语言【insert update delete】

DQL-数据查询语言【select】

DDL-数据定义语言【create drop truncate】

DCL-数据控制语言【grant revoke】

TCL-事务控制语言【commit rollback】

数据库命令:DESC、SHOWUSER、CALL

PL/SQL过程化语言/结构化查询语言。

二、变量

【变量的声明】

变量名 【CONSTANT】 类型 【NOT NULL】 【:=value】

--变量的命名规则:建议以v_开头,尽快可以让人望文生义

 

【变量的赋值】

--1、声明时直接赋值
--2、在程序执行部分begin中赋值
--(1)使用:=
--(2)使用select into 方式
--3、type 和 rowtype

示例如下:

DECLARE
 v_name emp.ename%TYPE := 'jiazi'; --类型和表中对应字段类型一直保持一致,可以通过表名.列名%TYPE来声明类型;
 v_emp_rec emp%ROWTYPE; --数据集类型,b表名%ROWTYPE,但是只能接受一行数据不能多行,多行需用后面讲到的游标;
 v_gender VARCHAR2(10) NOT NULL :='女'; --非空,必须赋值
 v_no CONSTANT NUMBER :=1; --常量 必须赋值,并且不能被更改值
 v_date DATE;
BEGIN
 SELECT hiredate INTO v_date FROM emp WHERE ename='SCOTT';
 dbms_output.put_line('hello'||v_no||'班的'||v_name||',性别是:'||v_gender||',出生日期是:'||v_date);
 v_name :='jack';

---- jack的性别和emp表中scott性别一样,scott性别是根据empno奇男偶女决定;
/*SELECT DECODE(MOD(empno,2),0,'女',1,'男')
INTO v_gender
FROM emp
WHERE ename='SCOTT';*/

--dbms_output.put_line('hello'||v_no||'班的'||v_name||',性别是:'||v_gender);
SELECT * INTO v_emp_rec FROM emp WHERE ename='SCOTT';
dbms_output.put_line('v_emp_rec变量集的值:'|| v_emp_rec.empno);
END;

三、执行顺序(程序结构)

1、顺序结构

2、条件分支结构IF

例1:给员工加薪水,规则如下:

如果全员平均工资<1000,那么涨薪20%;

10000-2000,15%

2000-3000,10%

其他情况 5%。

 

DECLARE
v_avgsal NUMBER(8,2);--用于存放平均工资
v_num NUMBER(8);--用于存放涨薪数值
BEGIN
SELECT AVG(sal) INTO v_avgsal FROM emp;
IF v_avgsal<=1000 THEN
v_num:=20;
ELSIF v_avgsal<=2000 THEN
v_num:=15;
ELSIF v_avgsal <=3000 THEN
v_num:=10;
ELSE
v_num:=5;
END IF;
dbms_output.put_line('涨薪'||v_num||'%');
END;

 

3、循环结构 LOOP WHILE FOR

(1)Loop 直接进入循环,需要有退出条件

LOOP

执行语句;

EXIT WHEN 布尔表达式;

END LOOP;

(2)While 有条件进入循环,条件不满足,退出循环

WHILE 条件 LOOP

执行语句;

END LOOP;

(3)For 直接界定循环的最低和最高值,达到条件后退出

FOR 计数器 IN [REVERSE] 最低值.. 最高值 LOOP

 执行语句;

END LOOP;

plsql循环控制

例:循环打印1到10
--LOOP方式:


DECLARE
v_num NUMBER(8) := 1;
BEGIN
LOOP
dbms_output.put_line(v_num);
v_num := v_num+1;
EXIT WHEN v_num>10;
END LOOP;
END;

--while方式

DECLARE
v_num NUMBER(8) := 1;
BEGIN
WHILE v_num <=10 LOOP
dbms_output.put_line(v_num);
v_num := v_num+1;
END LOOP;
END;
--For方式

BEGIN
FOR v_num IN 1..10 LOOP
dbms_output.put_line(v_num);
END LOOP;
END;

四、游标Cursor

---先写一个题引出:打印20部门的员工的编号、姓名、工资

DECLARE
  v_emp_rec emp%ROWTYPE;
BEGIN
  SELECT * INTO v_emp_rec FROM emp WHERE deptno=20;
  dbms_output.put_line(v_emp_rec.emp||' / ' ||v_emp_rec.ename);
END;
---打印报错值过多,因为一个变量最多只能接收一行数据;
--于是可以用游标来指代一个select查询结果集,通过对游标操作按行提取数据;

【游标语法】
1、定义
CURSOR 游标名 IS SELECT 语句;
2、打开游标
OPEN 游标名;
3、提取游标数据
FETCH 游标名 INTO 变量;
4、处理数据
5、关闭游标
CLOSE 游标名;
开头实例正确写法:
---1、LOOP方式
DECLARE
emp_rec emp%ROWTYPE;
CURSOR cur_emp IS
SELECT * FROM emp WHERE deptno = 20;
BEGIN
OPEN cur_emp;
LOOP
FETCH cur_emp
INTO emp_rec;
EXIT WHEN cur_emp%NOTFOUND;
dbms_output.put_line(emp_rec.ename || ' 薪资:' || emp_rec.sal);
END LOOP;
CLOSE cur_emp;
END;
---2、while方式

DECLARE
emp_rec emp%ROWTYPE;
CURSOR cur_emp IS
SELECT * FROM emp WHERE deptno=20;
BEGIN
OPEN cur_emp;
FETCH cur_emp INTO emp_rec;
WHILE cur_emp%FOUND LOOP
dbms_output.put_line(emp_rec.ename || ' 薪资:' || emp_rec.sal);
FETCH cur_emp INTO emp_rec;
END LOOP;
CLOSE cur_emp;
END;

---3、for方式
DECLARE
emp_rec emp%ROWTYPE;
CURSOR cur_emp IS
SELECT * FROM emp WHERE deptno=20;
v_cnt NUMBER(8);
BEGIN
SELECT COUNT(*) INTO v_cnt FROM emp WHERE deptno=20;
OPEN cur_emp;
FOR v_in IN 1.. v_cnt LOOP
FETCH cur_emp INTO emp_rec;
dbms_output.put_line(emp_rec.ename || ' 薪资:' || emp_rec.sal);
END LOOP;
CLOSE cur_emp;
END;

--游标for循环(Oracle特有的游标写法,可以简化游标的操作,不需要open\fetch操作,重点记住)

DECLARE
CURSOR cur_emp IS
SELECT * FROM emp WHERE deptno=20;
BEGIN
FOR v_emp_rec IN cur_emp LOOP
dbms_output.put_line(v_emp_rec.ename || ' 薪资:' || v_emp_rec.sal);
END LOOP;
END;

---游标属性
----1、游标名%rowcount 返回游标fetch成功的数据条数,如果游标没有fetch,那么值为0;
----2、游标名%notfound 返回最近一次读取是否失败
----3、游标名%found 返回最近一次读取是否成功

--隐形游标,系定义的游标,没有明确的声明和操作过程,
--一般我们在insert\update\dalete数据时系统会自动创建游标;

BEGIN
INSERT INTO dept_bak SELECT * FROM dept;
dbms_output.put_line(SQL%ROWCOUNT);
END;

--作业:使用游标,删除部门表中名字相同的记录,但要保留最后一次添加的部门(部门编号最大的)

首先插入名字相同但部门号小的数据:
INSERT INTO dept_bak VALUES(8,'ACCOUNTING','A');
INSERT INTO dept_bak VALUES(12,'RESEARCH','B');
INSERT INTO dept_bak VALUES(15,'RESEARCH','C');
INSERT INTO dept_bak VALUES(25,'OPERATIONS','D');

--思路:按dname分组,筛选出count(*)大于1的,
--找出每组max(deptno),删除名字为dname但deptno不等于max(deptno)的行数据;

查询SQL:SELECT dname,MAX(deptno) AS maxdno
FROM dept_bak
GROUP BY dname
HAVING COUNT(*)>1;

测试成功后开始:
DECLARE
CURSOR cur_dept IS SELECT dname,MAX(deptno) AS maxdno
FROM dept_bak
GROUP BY dname
HAVING COUNT(*)>1;
BEGIN
FOR v_dept_rec IN cur_dept LOOP
dbms_output.put_line(v_dept_rec.dname||' ,maxno: '||v_dept_rec.maxdno);
DELETE FROM dept_bak WHERE dname=v_dept_rec.dname AND deptno!=v_dept_rec.maxdno;
END LOOP;
END;

测试:SELECT * FROM dept_bak;

五、异常

语法:
DECLARE
BEGIN
EXCEPTION
WHEN exception类型 THEN ...
WHEN exception类型 THEN ...
WHEN OTHERS THEN ...
END;

/*常见异常:
NO_DATA_FOUND select ino 没有找到数据
TOO_MANY_ROWS select into 返回多行
ZERO_DIVIED 被零除
INVALID_NUMBER 转换数字失败
*/

DECLARE
v_num NUMBER:=1;
v_result NUMBER;
BEGIN
v_result :=10/v_num;
SELECT empno INTO v_result FROM emp;
dbms_output.put_line(v_result);
EXCEPTION
WHEN zero_divide THEN dbms_output.put_line('被零除错误');
WHEN TOO_MANY_ROWS THEN dbms_output.put_line('返回多行');
WHEN OTHERS THEN dbms_output.put_line('有其它异常');
END;

 

标签:END,--,游标,emp,SQL,Oracle,rec,LOOP
From: https://www.cnblogs.com/jxlizi/p/18604420

相关文章

  • sql server 2008 r2 展开时报错:参数名:viewInfo ( Microsoft SqlServer Management S
    HR服务器的数据库报了一个不常见的错误,记录下来分享给大伙,如果遇到同样的问题,希望可以得到解决。服务器环境:windowsserver2008(64Bit)数据库版本:SQLserver2008R2错误提示:值不能为空。参数名:viewInfo(Microsoft.SqlServer.Management.SqlStudio.Expl;如下图:  在路径:C:\Us......
  • 免费送源码:Java+ssm+MySQL SSM智慧旅游系统 计算机毕业设计原创定制
     摘要随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。智慧旅游系统设计,主要的模块包括查看首页、站点内容(轮播图、公告栏)系统用户(管理员、注册用户、导游)公共内容(旅游资讯、资讯分类)模块管理(地区管理、景点信息......
  • 免费送源码:Java+B/S+MySQL 多元化智能选课系统的设计与实现 计算机毕业设计原创定制
    摘 要多元化智能选课系统使用Java语言的Springboot框架,采用MVVM模式进行开发,数据方面主要采用的是微软的Mysql关系型数据库来作为数据存储媒介,配合前台技术完成系统的开发。论文主要论述了如何使用JAVA语言开发一个多元化智能选课系统,本系统将严格按照软件开发流程进行各个......
  • MySQL 事务
     概念介绍         事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。MySQL提供一种机制,保证我们达到这样的效果。        事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。假......
  • Mac安装mysql8.0版本数据库
    一、环境和所需软件概述1.1目前环境:MacOS(10.15.3)1.2所需软件:mysql-8.0.18-macos10.15-x86_64.dmg(8.0系列都可以)二、安装步骤(全部采用高清大图吧!!)2.1进入mysql安装包下载页面,下版本的dmg文件,下载地址如下:msyql官网下载地址-------------图一-----------------......
  • Linux安装MySQL8.0
    在linux系统的下切换到/usr/local目录下创建mysql文件夹,也可以自定义文件夹。#切换目录cd/usr/local#创建文件夹mkdirmysql切换到刚创建的目录下,并使用wget下载mysql压缩包。我们选择MySQL8.0.20cdmysqlwgethttps://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8......
  • Windows安装MySQL8.0
    一、下载MySQL安装包MySQL直接去官网下载就行,选择community版本(免费)下载,链接:https://dev.mysql.com/downloads/mysql/。在“MySQLCommunityServer”页面,根据您的Windows系统版本(32位或64位)选择合适的安装包进行下载。一般来说,现在大多数电脑都是64位系统,我们以6......
  • 【linux下mysql主从复制操作流程】
    linux下mysql主从复制操作流程在Linux下实现MySQL主从复制(Master-SlaveReplication)是一个常见的需求,用于读写分离、数据备份等场景。以下是一个详细的操作流程,包括每个步骤、注意事项以及总结。一、准备环境安装MySQL确保主服务器(Master)和从服务器(Slave)都已经安装了My......
  • centos 7 普通用户安装mysql8 安装包2. 使用lsb_release a命令1. 使用cat /etc/redhat
       [root@bigdatapackage333]#rpm-qa|grepmariadbmariadb-libs-5.5.64-1.el7.x86_64[root@bigdatapackage333]#rpm-qa | grepmysql[root@bigdatapackage333]#[root@bigdatapackage333]#rpm-e--nodepsmariadb-libs-5.5.64-1.el7.x86_64[root@bigdatapack......
  • 我们来学mysql -- 事务并发之不可重复读(原理篇)
    事务并发之不可重复读题记不可重复读系列文章题记在《事务之概念》提到事务对应现实世界的状态转换,这个过程要满足4个特性这世界,真理只在大炮射程之类,通往和平的道路,非“常人”可以驾驭一个人生活按部就班,人多起来,难免鸡飞狗跳同理现实世界的状态转换映射到数据库,满......