数据库武林秘史(三)PL/SQL流程控制的内功心法
点击上方蓝字,关注我们
想学会更多实用技巧,欢迎加入青学会MOP技术社区(实名社区)。
加入方法:公众号后台回复关键字“加入”获取小助手微信,添加后登记入会。
同时欢迎大家在评论区留言互动交流!社区会不定期举行相关的抽奖、公开分享活动。
如果你有想了解的知识点希望我们发文可以后台私信。
正文开始
在数据处理的江湖中,PL/SQL以其强大的流程控制语句,成为Oracle数据库开发者手中的利器。继上次学习了PL/SQL块结构和组成元素后,小倩对这门技艺的兴趣愈发浓厚。智海大师见状,决定带领小倩深入探索PL/SQL的流程控制语句,这是成为优秀数据库开发者的必经之路。今天,他们将聚焦于条件语句、循环语句和顺序语句,这些是编写高效、可维护代码的关键。
条件语句
智海大师首先向小倩介绍了条件语句,这是PL/SQL中最基本的流程控制结构之一。
IF语句
IF语句允许根据布尔表达式的真假来执行不同的代码块。大师展示了IF语句的基本结构:
IF <布尔表达式1> THEN-- PL/SQL 和 SQL 语句END IF;IF <布尔表达式2> THEN-- PL/SQL 和 SQL 语句ELSE-- 其它语句END IF;IF <布尔表达式3> THEN-- PL/SQL 和 SQL 语句ELSIF <其它布尔表达式1> THEN-- 其它语句ELSIF <其它布尔表达式2> THEN-- 其它语句ELSE-- 其它语句END IF;
并特别提醒小倩,ELSIF不能写成ELSEIF。
例1:根据工资评定员工
为了加深理解,智海大师让小倩编写一个根据员工工资评定的PL/SQL块:
DECLAREv_empno emp.empno%TYPE := &empno; -- 声明并初始化员工编号变量v_salary emp.sal%TYPE; -- 声明薪水变量v_comment VARCHAR2(35); -- 声明评论变量BEGINSELECTsal INTO v_salary FROM emp WHERE empno = v_empno; -- 从数据库获取薪水IF v_salary < 1500 THENv_comment := 'Fairly less'; -- 如果薪水小于1500,设置评论为'Fairly less'ELSIF v_salary < 3000 THENv_comment := 'A little more'; -- 如果薪水在1500到3000之间,设置评论为'A little more'ELSEv_comment := 'Lots of salary'; -- 如果薪水大于或等于3000,设置评论为'Lots of salary'ENDIF;DBMS_OUTPUT.PUT_LINE(v_comment); -- 输出评论END;
CASE表达式
接着,智海大师介绍了CASE表达式,这是一种更简洁的条件选择语句。
CASE selectorWHEN expression1 THEN result1WHEN expression2 THEN result2...WHEN expressionN THEN resultN[ ELSE resultN+1 ]END;
例2:根据成绩评定等级
小倩根据大师的指导,编写了一个根据成绩评定等级的PL/SQL块:
DECLAREv_grade CHAR(1) := UPPER('&p_grade'); -- 声明并初始化成绩变量,转换为大写v_appraisal VARCHAR2(20); -- 声明评价变量BEGINv_appraisal := CASE v_gradeWHEN 'A' THEN 'Excellent'-- 如果成绩是'A',评价为'Excellent'WHEN 'B' THEN 'Very Good'-- 如果成绩是'B',评价为'Very Good'WHEN 'C' THEN 'Good'-- 如果成绩是'C',评价为'Good'ELSE'No such grade'-- 如果成绩不是'A', 'B', 'C'中的任何一个,评价为'No such grade'END;DBMS_OUTPUT.PUT_LINE('Grade: ' || v_grade || ' Appraisal: ' || v_appraisal); -- 输出成绩和评价END;
循环
智海大师强调,循环是处理重复任务的关键。
简单循环
简单循环允许在满足特定条件之前重复执行代码块。
LOOP-- 要执行的语句-- 这里放置循环体中的代码EXIT WHEN <条件语句>; -- 当条件语句为真时,退出循环-- 如果需要在退出循环前执行其他语句,可以在这里添加END LOOP;
例3:打印数字1到10
小倩根据大师的指导,编写了一个打印数字1到10的PL/SQL块:
DECLAREintNUMBER(2) := 0; -- 声明一个数字变量,初始值为0BEGINLOOPint := int + 1; -- 将int的值增加1DBMS_OUTPUT.PUT_LINE('int 的当前值为: ' || int); -- 输出当前int的值EXIT WHENint=10; -- 当int的值达到10时,退出循环END LOOP;END;
WHILE循环
WHILE循环在布尔表达式为真时重复执行代码块。
WHILE <布尔表达式> LOOP-- 要执行的语句-- 这里放置循环体中的代码END LOOP;
例4:打印数字1到10
小倩根据大师的指导,编写了一个使用WHILE循环打印数字1到10的PL/SQL块:
DECLAREx NUMBER; -- 声明数字变量xBEGINx := 1; -- 初始化x为1WHILE x < 10 LOOPDBMS_OUTPUT.PUT_LINE('X的当前值为: ' || x); -- 输出当前x的值x := x + 1; -- 将x的值增加1END LOOP;END;
数字式循环
数字式循环允许在指定范围内迭代。
FOR 循环计数器 IN [REVERSE] 下限 .. 上限 LOOP-- 要执行的语句-- 这里放置循环体中的代码END LOOP;
例5:打印数字1到10
小倩根据大师的指导,编写了一个使用数字式循环打印数字1到10的PL/SQL块:
BEGINFORintIN1..10 LOOPDBMS_OUTPUT.PUT_LINE('int 的当前值为: '||int);END LOOP;END;
标签和GOTO
智海大师解释说,GOTO语句用于无条件跳转到指定的标签。
GOTO label; -- 跳转到标签label<<Label>> -- 标签名称,用<<>>括起来BEGIN-- 标签下的代码块-- 这里放置标签下的代码END <<Label>>;
例7:使用GOTO跳转
小倩根据大师的指导,编写了一个使用GOTO跳转的PL/SQL块:
DECLAREV_counter NUMBER :=1;BEGINLOOPDBMS_OUTPUT.PUT_LINE('V_counter的当前值为: '|| V_counter);V_counter := V_counter +1;IF V_counter >10THENGOTO 1_ENDofLOOP;END IF;END LOOP;<<1_ENDofLOOP>>DBMS_OUTPUT.PUT_LINE('V_counter的当前值为: '|| V_counter);END;
NULL语句
智海大师最后介绍了NULL语句,它用于表示“不用做任何事情”。
DECLAREv_num NUMBER;BEGINIF v_num ISNULLTHENGOTO print1;END IF;-- 其他代码逻辑<<print1>>DBMS_OUTPUT.PUT_LINE('NULL; -- 不需要处理任何数据。');END;
夜幕低垂,智海大师的居所内灯光依旧明亮。小倩站在门外,心中既兴奋又紧张。过去几个月,在大师的指导下,她已经熟练掌握了PL/SQL流程控制语句。当她推开门时,智海大师的话让她愣住了。
“你做得很好,但前方还有更险峻的挑战——Oracle数据库游标的使用。”大师的目光深邃,“掌握游标的使用,才能真正掌控数据流,实现复杂的数据处理。”
小倩心中一震,意识到自己还有更多需要学习。智海大师承诺,下次见面将传授这些关键技巧,并分享一位前辈的故事,这位前辈曾以精湛的游标使用技艺化解了一场数据库危机,被誉为“数据库之王”。
带着新的目标和期待,小倩离开了智海山,准备迎接即将到来的挑战,书写属于自己的传奇。
往期文章回顾
MOP社区新闻
金仓专栏
告别繁琐!KingbaseES v9数据库一键安装-青学会&金仓专栏(1)
KingbaseES v9数据库Docker安装-青学会&金仓专栏(2)
DBA实战小技巧
实战:记一次RAC故障排查
DBA实战运维小技巧安装篇(一)Oracle 主流版本不同架构下的静默安装指南
DBA实战运维小技巧存储篇(一)根目录满了如何处理
DBA实战运维小技巧存储篇(二)打包迁移单机数据库至新存储
MOP社区投稿-内核开发
简单解析 IvorySQL 增强 Oracle xml 兼容能力的原理
简单讨论 PostgreSQL C语言拓展函数返回数据表的方式
简单分析 pg_config 程序的作用与原理
Redis 日志机制简介(一):SlowLog
Redis 日志机制简介(二):AOF 日志
Redis 日志机制简介(三):RDB 日志
pg_cron插件使用介绍
Redis 的指令表实现机制简介
pg几款源码工具介绍
Redis 事务功能简介