Oracle PL/SQL Programming 第5章:Iterative Processing with Loops 读书笔记

这篇具有很好参考价值的文章主要介绍了Oracle PL/SQL Programming 第5章:Iterative Processing with Loops 读书笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

总的目录和进度,请参见开始读 Oracle PL/SQL Programming 第6版

本章探讨 PL/SQL 的迭代控制结构(也称为循环),它允许您重复执行相同的代码。

PL/SQL 提供了三种不同类型的循环结构:

  • 简单或无限循环
  • FOR 循环(数字和游标)
  • WHILE 循环

每种类型的循环都是针对特定目的而设计:

属性 描述
循环如何终止 循环重复执行代码。 如何使循环停止执行其主体?
何时进行终止测试 终止测试是在循环的开始还是结束时进行? 后果是什么?
使用此循环的原因 您应该考虑哪些特殊因素来确定此循环是否适合您的情况?

Loop Basics

为什么存在三种不同类型的循环? 为了给您提供灵活性,为了代码简单,更容易理解和维护。

Examples of Different Loops

简单或无限循环:

LOOP
    EXIT WHEN i > 100;
    ...;
    i:=  i + 1;
END LOOP;

FOR循环(数字):

FOR i IN 1 .. 100
LOOP
   ...;
END LOOP;

FOR循环(游标):

FOR i IN (SELECT ...)
LOOP
   ...;
END LOOP;

WHILE循环:

WHILE (i <= 100)
LOOP
   ...;
END LOOP;

Structure of PL/SQL Loops

虽然这三个循环结构之间存在差异,但每个循环都有两个部分:

  • 循环边界
    它由启动循环的保留字、导致循环终止的条件以及结束循环的 END LOOP 语句组成。

  • 循环体
    这是循环边界内的可执行语句序列,在循环的每次迭代中执行。

The Simple Loop

形式为:

LOOP
  执行语句...
END LOOP;

仅当执行语句包含EXIT或EXIT WHEN时,才会退出循环;否则为无限循环。

EXIT;
EXIT WHEN 判断条件;

EXIT WHEN等同于IF-THEN加EXIT。

使用简单循环的场景:

  • 希望循环至少执行1次
  • 无法确定循环需执行多少次

当存在单个条件表达式来确定循环是否应终止时,最好使用 EXIT WHEN。 在有多个退出条件的情况下,或者当您需要根据不同的条件设置从循环中退出时,最好使用 IF 或 CASE 语句,然后加上EXIT 语句 。

Emulating a REPEAT UNTIL Loop

PL/SQL中没有WHILE…UNTIL语句,但有类似的实现:

LOOP
   ...
   EXIT WHEN ...;
END LOOP;

The Intentionally Infinite Loop

无限循环可能存在,但通常都会加sleep语句:

LOOP 
   执行操作;
   DBMS_LOCK.sleep(10);
END LOOP;

如何终止无限循环?在交互式PL/SQL中可以用“Ctrl+C”,在后台运行的程序可以用操作系统的kill命令,注意数据库中的ALTER SYSTEM KILL SESSION命令不一定可以终止无限循环。但是kill命令有可能误杀,例如在共享服务器模式下。

作者推荐的方式为利用PL/SQL中的管道,这类似于Shell编程中的信号:

DECLARE
   pipename CONSTANT VARCHAR2(12) := 'signaler';
   result INTEGER;
   pipebuf VARCHAR2(64);
BEGIN
   /* create private pipe with a known name */
   result := DBMS_PIPE.create_pipe(pipename);

   LOOP
      DBMS_OUTPUT.PUT_LINE('I''m doing works ...'); -- 请替换为实际执行的操作
      DBMS_LOCK.sleep(5);

      /* see if there is a message on the pipe */
      IF DBMS_PIPE.receive_message(pipename, 0) = 0
      THEN
         /* interpret the message and act accordingly */
         DBMS_PIPE.unpack_message(pipebuf);
         IF pipebuf = 'stop'
         THEN
         	DBMS_OUTPUT.PUT_LINE('Exiting ...');
         	EXIT;
         END IF;
      END IF;
   END LOOP;
END;

上面是接收信号的程序,下面是发送信号的程序:

DECLARE
   pipename   VARCHAR2 (12) := 'signaler';
   result     INTEGER := DBMS_PIPE.create_pipe (pipename);
BEGIN
   DBMS_PIPE.pack_message ('stop');
   result := DBMS_PIPE.send_message (pipename);
END;

测试在SQL Plus中通过,但SQL Developer没有通过,不知为何。
以下为成功时的输出:

I'm doing works ...
I'm doing works ...
I'm doing works ...
I'm doing works ...
I'm doing works ...
Exiting ...

PL/SQL procedure successfully completed.

此示例使用私有管道,因此发送和接收程序需为同一用户。 另请注意,私有管道的数据库命名空间在当前用户运行的所有会话中是全局的。

The WHILE Loop

如事先不知道循环执行的次数(可以一次都不执行),则可使用 WHILE 循环:

WHILE 布尔变量|表达式
LOOP
   执行语句
END LOOP;

The Numeric FOR Loop

PL/SQL FOR 循环有两种:数字FOR 循环和游标FOR 循环。 数字 FOR 循环是传统且熟悉的“计数”循环。 FOR 循环的迭代次数在循环开始时就已知。

范围方案隐式声明循环索引(如果尚未声明),指定范围的起点和终点,并可选择指定循环索引进行的顺序(从最低到最高或从最高到最低)。

FOR loop index IN [REVERSE] lowest number .. highest number
LOOP
   executable statement(s)
END LOOP;

Rules for Numeric FOR Loops

  • 不要声明循环索引。 PL/SQL 自动且隐式地将其声明为数据类型为 INTEGER 的局部变量。 该索引的范围是循环本身; 您不能在循环外引用循环索引。
  • 范围方案中使用的表达式(最低和最高边界)在循环开始时评估一次。 在循环执行期间不会重新评估范围。所以,后面改了也不会生效。
  • 切勿在循环内更改循环索引或范围边界的值。

Examples of Numeric FOR Loops

一个倒计时程序:

BEGIN
FOR i IN REVERSE 1 .. 10
LOOP
   DBMS_OUTPUT.PUT_LINE(i);
END LOOP;
END;

还有范围可以由常数定义,也可以由变量或表达式定义。

Handling Nontrivial Increments

和C语言不一样,PL/SQL中的循环索引的步增/步减永远是1。所以,如果增减量为非1,则需要另加IF判断,如MOD函数。

The Cursor FOR Loop

游标 FOR 循环是与直接合并在循环边界内的显式游标或 SELECT 语句关联(并实际由其定义)的循环。 仅当需要从游标中获取并处理每条记录时(游标经常出现这种情况),才使用游标 FOR 循环。

游标 FOR 循环充分利用了过程结构与 SQL 数据库语言的强大功能的紧密且有效的集成。 它减少了从游标获取数据所需编写的代码量。 它大大减少了在编程中引入循环错误的机会,而循环是程序中最容易出错的部分之一。

FOR record IN { cursor_name | (explicit SELECT statement) }
LOOP
   executable statement(s)
END LOOP;

其中 record 是由 PL/SQL 使用 %ROWTYPE 属性针对cursor_name 指定的游标隐式声明的记录。

不要显式声明与循环索引记录同名的记录。 它不是必需的(PL/SQL 隐式声明它在循环中使用)并且可能导致逻辑错误。 有关在循环执行之外或之后访问有关游标 FOR 循环记录的信息的提示,请看本文后面部分:Obtaining Information About FOR Loop Execution。

Example of Cursor FOR Loops

没有用游标FOR循环之前:

SET SERVEROUTPUT ON
DECLARE
   CURSOR hr_cur IS
      SELECT first_name, last_name
        FROM employees WHERE department_id = 100;
   hr_rec hr_cur%ROWTYPE;
BEGIN
   OPEN hr_cur;
   LOOP
      FETCH hr_cur INTO hr_rec;
      EXIT WHEN hr_cur%NOTFOUND;
      DBMS_OUTPUT.PUT_LINE(hr_rec.first_name || ' ' || hr_rec.last_name);
    END LOOP;
    CLOSE hr_cur;
 END;

用游标FOR循环后,简洁很多! 无需记录的声明。 OPEN、FETCH 和 CLOSE 语句已消失。 不再需要检查 %NOTFOUND 属性。:

SET SERVEROUTPUT ON
DECLARE
   CURSOR hr_cur IS
      SELECT first_name, last_name
        FROM employees WHERE department_id = 100;
BEGIN
    FOR hr_rec IN hr_cur
    LOOP
        DBMS_OUTPUT.PUT_LINE(hr_rec.first_name || ' ' || hr_rec.last_name);
    END LOOP;
 END;

与所有其他游标一样,您可以在游标 FOR 循环中将参数传递给游标?。 如果光标选择列表中的任何列是表达式,请记住您必须在选择列表中为该表达式指定别名。 在循环内,访问游标记录中特定值的唯一方法是使用点符号(record_name.column_name,如 ocupancy_rec.room_number),因此您需要一个与表达式关联的列名。

Loop Labels

您可以使用标签为循环命名。 格式为:

<<label_name>>

<<label_name>> 必须出现在循环体第一个语句之前,而在END LOOP也可以加label_name,但不是必须。

循环标签作用:

  • 代码更容易维护和调试。就好像括号必须成对出现。
  • 可使用标签来限定循环索引变量的名称,这有助于提高可读性。
  • 当您有嵌套循环时,您可以使用标签来提高可读性并增强对循环执行的控制。如EXIT loop_label [WHEN condition];不过这种用户和GOTO一样不建议。

The CONTINUE Statement

CONTINUE 语句退出循环的当前迭代,并立即继续该循环的下一次迭代。 该语句有两种形式,就像 EXIT 一样:无条件 CONTINUE 和条件 CONTINUE WHEN。

下例演示了利用CONTINUE实现步进为3:

BEGIN
   FOR l_index IN 1 .. 10
   LOOP
      CONTINUE WHEN MOD (l_index - 1, 3) != 0;
      DBMS_OUTPUT.PUT_LINE ('Loop index = ' || TO_CHAR (l_index));
   END LOOP;
END;
/

输出为:

Loop index = 1
Loop index = 4
Loop index = 7
Loop index = 10

您还可以使用 CONTINUE 终止内部循环并立即继续进行外部循环体的下一次迭代。 为此,您需要使用标签为外部循环命名。

IS CONTINUE AS BAD AS GOTO?

continue 语句不能滥用,但用对地方则很有价值,因为它使代码更短,使代码更易于阅读,并减少了对布尔变量的需求。

作者举了使用和不使用continue的2个例子作为对比。我看懂了,并认可。

使用continue的例子:

LOOP
   EXIT WHEN exit_condition_met;
   CONTINUE WHEN condition1;
   CONTINUE WHEN condition2;
   setup_steps_here;

   IF condition4 THEN
      action4_executed;
      CONTINUE;
   END IF;

   IF condition5 THEN
      action5_executed;
      CONTINUE; -- Not strictly required.
   END IF;
END LOOP;

如果不使用continue:

LOOP
   EXIT WHEN exit_condition_met;

   IF condition1
   THEN
      NULL;
   ELSIF condition2
   THEN
      NULL;
   ELSE
      setup_steps_here;

      IF condition4 THEN
         action4_executed;
      ELSIF condition5 THEN
         action5_executed;
      END IF;
   END IF;
END LOOP;

Tips for Iterative Processing

循环是非常强大且有用的结构,但您应该谨慎使用它们。 程序中的性能问题通常可以追溯到循环,并且循环中的任何问题都会因其重复执行而被放大。 确定何时停止循环的逻辑可能非常复杂。 本节提供了一些关于如何编写干净、易于理解且易于维护的循环的技巧。

Use Understandable Names for Loop Indexes

使用有意义的循环索引变量名称,而非简单的i,j,k。

The Proper Way to Say Goodbye

结构化编程的一个重要且基本的原则是“一进一出”; 也就是说,程序应该有一个入口点和一个出口点。一个入口是必然的,这里讲的是如何避免多个出口。

您应该遵循以下循环终止准则:

  • 不要在 FOR 和 WHILE 循环中使用 EXIT 或 EXIT WHEN 语句。
  • 不要在循环中使用 RETURN 或 GOTO 语句,这同样会导致循环过早、非结构化终止。

如果需要根据游标 FOR 循环获取的信息终止循环(例如当取得值的合计大于某值时退出),则应使用 WHILE 循环或简单循环代替。 那么代码的结构就会更清楚地表达你的意图。

Obtaining Information About FOR Loop Execution

FOR 循环是方便且简洁的结构,对于游标 FOR 循环尤其如此。 然而,有一个权衡:数据库自动为您完成大量工作,但您在循环终止后对有关循环最终结果的信息的访问受到限制。

简单来说,游标 FOR 循环的END LOOP语句后,游标就被关闭了,也就是说,此时无法获取游标的信息。因此,你需要再循环内部(游标关闭前)暂存游标的信息,如行数(cursor%ROWCOUNT),后续关闭后就可以继续访问。

SQL Statement as Loop

实际上,您可以将像 SELECT 这样的 SQL 语句视为循环。 毕竟,这样的语句指定了对一组数据采取的操作; 然后,SQL 引擎“循环”数据集并应用操作。

例如一个数据归档的例子,从源表中逐行读取,然后插入归档表后删除。这既可以用PL/SQL实现,也可以用2条SQL实现(INSERT INTO … DELETE,DELETE )

SQL实现编写的代码更少,而且运行效率更高,因为减少了上下文切换的次数(在 PL/SQL 和 SQL 执行引擎之间来回移动)。 只执行一次插入和一次删除。

但SQL的灵活性差一点,因为SQL是事务型的,要么全成功,要么全失败;SQL也不能做特殊处理,如记录归档失败的记录。因此,PL/SQL 提供更大的灵活性。

总之,PL/SQL 提供一次访问和处理单行并采取操作(或许还有基于该特定记录内容的复杂过程逻辑)的能力。 另一方面,使用原生SQL代码更少,运行效率更高。必要时,可以混合使用 PL/SQL 和 SQL。文章来源地址https://www.toymoban.com/news/detail-830982.html

单词

  • go figure 多奇怪!多怪异!多愚蠢!

到了这里,关于Oracle PL/SQL Programming 第5章:Iterative Processing with Loops 读书笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ORACLE数据库 —— PL/SQL知识点2

    ORACLE数据库  PL/SQL语句基础知识点  适合有SQL基础的人群。  禁止转载! 内置函数 字符串函数     lower(列名|字符串)函数用于返回字符串的小写形式。         eg.SELECT ename,sal FROM emp WHERE ename=lower(\\\'ename\\\');     upper(列名|字符串)函数用于返回字符串的大写形式。       

    2024年02月08日
    浏览(52)
  • Oracle/PL/SQL奇技淫巧之Json转表

    在Oracle中,有些时候我们需要在一个json文档中查数据 这个时候我们可以通过 JSON_TABLE 函数来把 json文档 提取成一张可以执行正常查询操作的表 先看 JSON_TABLE 函数的基础用法: 其中: json_data :要从中提取数据的 JSON文档 或 JSON列 $.json_path :JSON路径表达式,该表达式指定要提

    2024年02月12日
    浏览(41)
  • Oracle/PL/SQL奇技淫巧之ROWNUM伪列

    ROWNUM 是一个伪列,它是根据每次查询的结果动态生成的一列递增编号,表示 Oracle 从表中选择该行的顺序,选择的第一行 ROWNUM 为1,第二行 ROWNUM 为2,以此类推。 ROWNUM 伪列是在 WHERE 子句之前生成的,就是说它并不是在执行了 WHERE 子句过滤之后再对数据编号 比如在执行 WHE

    2024年02月12日
    浏览(41)
  • Oracle开发和应用——PL/SQL语法2(游标及集合)

    6.4.6.  游标 这里的游标 (cursor) ,是指数据库开发中的游标,而且,这里所指的是显式定义的游标。因为,除了显式定义的游标,我们每条SQL语句也会隐式的定义、打开和关闭一个游标,其实质是一个带有指针的结果集。当我们按照顺序取出结果时,这个指针会按照从前到

    2024年02月22日
    浏览(43)
  • Oracle PL/SQL基础语法学习13:比较运算符

    Oracle PL/SQL基础语法学习12:短路求值 Oracle PL/SQL基础语法学习13:比较运算符 Oracle PL/SQL基础语法学习14:BOOLEAN表达式 【免责声明】文章仅供学习交流,观点代表个人,与任何公司无关。 编辑|SQL和数据库技术(ID:SQLplusDB) 比较运算符是 PL/SQL 语言中的基本元素之一,它们被用于

    2024年02月05日
    浏览(51)
  • 用PL/SQL Developer连接远程Oracle数据库

    oracle数据库安装教程参考 注意: 第六步中的Oracle基目录中的用户名为中文的话,需要去掉中文部分。然后管理口令一定保存好。 2.打开oracle安装目录(默认在C盘,我的在D盘),找到tnsnames.ora文件 这是oracle客户端所需要的一个文件,通过该文件可以配置数据库的连接地址,

    2024年02月13日
    浏览(45)
  • PL/SQL+cpolar公网访问内网Oracle数据库

    Oracle,是甲骨文公司的一款关系数据库管理系统,它在数据库领域一直处于领先地位。可以说Oracle数据库系统是世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小微机环境。它是一种高效率的、可靠性好的、适应高吞吐量的数据

    2024年02月08日
    浏览(42)
  • PL/SQL Developer15和Oracle Instant Client安装配置

    Oracle Instant Client Downloads | Oracle 中国 PL/SQL Developer - Allround Automations Free trial - Allround Automations 一路默认下一步。 选择输入许可信息: 产品码: 4tqw83ltw4ustkjfftny7wjl7tqv9uscs8 序列号: 182522 密码: *************  一路默认下一步,直到安装完成。 解压到自己喜欢的位置即可。 Oracl

    2024年02月12日
    浏览(43)
  • 【数据库】日常使用PL/SQL 登录ORACLE 数据库查询数据

    一、PL/SQL 登录方式 username: ##访问数据库的账号 password: ##访问数据库的密码 Databse: ##数据库IP地址/实例名 数据库集群心跳地址/实例名 Connect as : ##Normal,如果使用sysdba账户登录选择SYSDBA 二、PL/SQL使用SQL语句查询 点击上方导航栏,New,选择SQL Window,即可再次输入要查询的

    2024年02月19日
    浏览(70)
  • 教你如何通过内网穿透轻松实现PL/SQL远程连接Oracle数据库【内网穿透】

    转发自CSDN远程穿透的文章:公网远程连接Oracle数据库【内网穿透】 Oracle,是甲骨文公司的一款关系数据库管理系统,它在数据库领域一直处于领先地位。可以说Oracle数据库系统是世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、

    2024年02月03日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包