当前位置: 首页 > news >正文

Oracle PL/SQL Programming 第3章:Language Fundamentals 读书笔记

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

每种语言(无论是人类语言还是计算机语言)都有语法、词汇和字符集。 为了使用该语言进行交流,您必须学习管理其使用的规则。 我们许多人对学习新的计算机语言持谨慎态度。 变化往往令人恐惧,但通常编程语言都非常简单,PL/SQL 也不例外。 在基于字节的语言中进行对话的困难不在于语言本身,而在于我们正在讨论的编译器或计算机。 大多数情况下,编译器都是相当愚蠢的。 他们不是有创造力的众生。 他们没有原创思想的能力。 他们的词汇量非常有限。 编译器只是碰巧以非常非常快的速度思考他们枯燥的想法,而且非常不灵活。

本章涵盖了帮助您与 PL/SQL 编译器进行交互的基本语言规则——PL/SQL 块结构、字符集、词法单元和 PRAGMA 关键字。

PL/SQL Block Structure

在 PL/SQL 中,最小的有意义的代码分组称为块。 块是一个代码单元,为变量声明和异常处理提供执行和范围边界。 PL/SQL 允许您创建匿名块(没有名称的代码块)和命名块,它们可以是包、过程、函数、触发器或对象类型。

PL/SQL 块最多有四个不同的部分,其中只有一个是必须的:

  • 标头:仅用于命名块。 标头确定必须调用命名块或程序的方式。 可选。
  • 声明部分:标识在执行和异常部分中引用的变量、游标和子块。 可选。
  • 执行部分:包含 PL/SQL 运行时引擎将在运行时执行的语句。 必须。
  • 异常部分:处理异常(警告和错误情况)。 可选。
标头
IS声明部分
BEGIN执行部分
EXCEPTION异常部分
END;

Anonymous Blocks

当有人希望保持匿名时,该人就不会被透露姓名。 这与 PL/SQL 中的匿名块相同,如下例所示:它完全没有标头部分,而是以 DECLARE 或 BEGIN 开头。 这意味着它不能被任何其他块调用——它没有可供引用的句柄。 相反,匿名块充当执行 PL/SQL 语句的容器,通常包括对过程和函数的调用。 由于匿名块可以有自己的声明和异常部分,因此开发人员经常嵌套匿名块以在较大的程序中提供标识符和异常处理的范围。

BEGINDBMS_OUTPUT.PUT_LINE('Hello, World!');
END;

匿名 PL/SQL 块的一般语法如下,中括号表示可选部分:

[ DECLARE   ... 声明语句 ... ]
BEGIN   ... 一个或多个执行语句 ...
[ EXCEPTION... 异常处理语句... ]
END;

匿名块执行一系列语句然后终止,因此就像过程一样。 事实上,所有匿名块都是匿名过程。 它们用于各种环境中,其中 PL/SQL 代码要么直接执行,要么包含在该环境中的某个程序中。 常见的例子包括:

  • 数据库触发器
    当某些事件发生时,数据库触发器会执行匿名块。

  • 即席命令或脚本文件
    在 SQL*Plus 或类似的执行环境中,匿名块从手动输入的块或从调用存储程序的脚本运行。 此外,SQL*Plus EXECUTE 命令通过将其参数包含在 BEGIN 和 END 语句之间,将其参数转换为匿名块。

  • 编译3GL(第三代语言)程序
    在 Pro*C 或 OCI 中,匿名块可以作为嵌入对存储程序的调用的方法。

在每种情况下,封闭匿名块的对象(无论是触发器、命令行环境还是已编译的程序)都提供上下文以及可能的程序命名方式。

Named Blocks

虽然匿名 PL/SQL 块是必不可少的,但您编写的大部分代码都将在命名块中。 匿名块和命名块的区别在于标头。 如下所示:

-- 过程的标头
PROCEDURE [schema.]name [ ( parameter [, parameter ... ] ) ][AUTHID {DEFINER | CURRENT_USER}]-- 函数的标头
FUNCTION [schema.]name [ ( parameter [, parameter ... ] ) ]RETURN return_datatype[AUTHID {DEFINER | CURRENT_USER}][DETERMINISTIC][PARALLEL ENABLE ...][PIPELINED [USING...] | AGGREGATE USING...]

由于 Oracle 允许您从 SQL 语句中调用某些函数,因此函数头包含比过程头更多的可选组件,与 SQL 运行时环境的功能和性能维度相对应。

Nested Blocks

PL/SQL 与 Ada 和 Pascal 共享块结构语言的附加定义,即块可以“嵌套”在其他块内,而且可以多级嵌套。 相比之下,C 语言有块,但标准 C 并不是严格的块结构,因为它的子程序不能嵌套。

您可能听到的有关嵌套块的其他术语包括封闭块、子块; 外围 PL/SQL 块可以称为封闭块或父块。

一般来说,嵌套块的优点是它为您提供了一种控制代码中的范围和可见性的方法。

Scope

在任何编程语言中,术语“范围”是指识别给定标识符所引用的“事物”的方式。 如果某个标识符出现多次,则该语言的作用域规则将定义将使用哪一个。 仔细控制标识符范围不仅会增加对运行时行为的控制,还会减少程序员意外修改错误变量的可能性。

在 PL/SQL 中,变量、异常、模块和一些其他结构对于声明它们的块来说是本地的。 当块停止执行时,您将无法再引用任何这些结构。 可以在过程中的任何位置引用外部块中的元素; 但是,内部块中声明的元素不可用于外部块。

每个 PL/SQL 变量都有一个范围:即可以在其中引用该变量的程序单元(块、子程序或包)的区域。

作者代码中的好习惯:变量定义遵循约定,即全局变量以g_开头,局部变量以l_开头

Qualify All References to Variables and Columns in SQL Statements

前面的例子,变量的引用是隐式的,下面是显式引用的例子:

PACKAGE BODY scope_demo
ISPROCEDURE set_global (number_in IN NUMBER)ISl_salary  ...;l_count   ...;BEGINDECLAREl_inner   PLS_INTEGER;BEGIN... set_global.l_count ...... local_block.l_inner ...... set_global.l_salary ...END local_block;scope_demo.g_global := set_global.number_in;END set_global;
END scope_demo;

可以看到,变量前面均加了范围指定符,如set_global是PROCEDURE名,local_block是BLOCK名,scope_demo是PACKAGE名。范围指定符均出现在END后面。

显式引用有几个好处:

  1. 提高代码的可读性
  2. 避免变量名称与列名称相同时可能出现的错误
  3. 充分利用 Oracle Database 11g 中提供的细粒度依赖性跟踪

我们先看前两个,第 20 章再解释第三个。

Improve readability

PL/SQL 程序中嵌入的几乎每个 SQL 语句都包含对列和变量的引用。 在小而简单的 SQL 语句中,区分这些不同的引用相对容易。 然而,在大多数应用程序中,您会发现非常长、极其复杂的 SQL 语句,其中包含数十甚至数百个对列和变量的引用。

如果您不限定这些引用,则很难一眼区分变量和列。 通过这些限定符,代码可以非常清楚地自我记录这些引用的来源。

尽管命名约定很有帮助,例如‘l_’开头表示局部变量,‘g_’开头表示全局变量。但并不足以保证随着时间的推移,PL/SQL 编译器始终按照您的预期解释您的标识符。

Avoid bugs through qualifiers

如果您没有限定对嵌入式 SQL 语句中所有 PL/SQL 变量的引用,那么今天正常工作的代码将来可能会突然不再工作。 而且可能很难找出问题所在。

例如下面这个没有指定范围限定符的例子。l_salary当时是个局部变量,但2年后,应用决定为表增加一列,也叫l_salary,此时就发生了冲突:

SELECT 
...  WHERE salary > l_salary;

在嵌入式 SQL 语句中,Oracle 数据库对未解析的标识符,会首先尝试将引用解析为指定表之一中的列。 如果找不到匹配项,它会尝试将引用解析为作用域内的 PL/SQL 变量。

所以你看,编译都没有错误,但业务逻辑就变了。这可能是一个非常难以追踪和修复的错误!

您还应该限定对这些嵌入式 SQL 语句中所有列名和变量的引用,而不是仅仅依靠命名约定来避免标识符之间的“冲突”。 那么,随着底层表的发展,您的代码将来出现异常行为的可能性就会大大降低。

Visibility

变量另一个重要的属性是它的可见性,即是否可以仅使用其名称来引用它,或者是否需要在其前面附加范围前缀。

Visible identifiers

可见标识符实际上可能引用以下任何内容:

  • 当前块中声明的标识符
  • 在包含当前块的块中声明的标识符
  • 您拥有的独立数据库对象(表、视图、序列等)或 PL/SQL 对象(过程、函数、类型)
  • 您拥有适当权限的独立数据库对象或 PL/SQL 对象,并且是您可以看到的 Oracle 同义词的目标
  • 循环索引变量(仅在循环体内可见且在范围内)

PL/SQL 还允许引用不直接可见的范围内项目,如下一节所述。

Qualified identifiers

不可见标识符的一个常见示例是包规范中声明的任何内容,例如变量、数据类型、过程或函数。 要引用该包外部的这些元素之一,您只需在其前面添加一个点限定符,类似于使用表名称限定列名的方式。

例如:

  • package.program
  • package.constant
  • schema.package.program
Qualifying identifier names with module names

必要时,PL/SQL 提供了许多方法来限定标识符,以便可以解析对该标识符的引用。 例如,使用包,您可以创建具有全局范围的变量。然后,我可以在包外部引用该变量,只要在标识符名称前面加上包名称即可。

默认情况下,分配给这些包级变量之一的值在当前数据库会话期间持续存在,直到会话断开。

除非显示指定,对变量的解析都是从内到外的。

SQL 的名称解析首先匹配列名称,而不是 PL/SQL 标识符。

Nested programs

PL/SQL 还提供了一个特别重要的功能,称为嵌套程序。 嵌套程序是完全出现在封闭块的声明部分内的过程或函数。 值得注意的是,嵌套程序可以引用先前在外部块中声明的任何变量和参数。

嵌套程序可以使您的程序更具可读性和可维护性,并且还允许您重用出现在块中多个位置的逻辑。 更多信息,请参阅第 17 章。

The PL/SQL Character Set

PL/SQL 程序由一系列语句组成,每个语句由一行或多行文本组成。 您可用的精确字符取决于您使用的数据库字符集。

PL/SQL 是一种不区分大小写的语言。 大写字母的处理方式与小写字母相同,除非被分隔符包围,使它们成为文字字符串。 按照惯例,本书作者更喜欢使用大写字母表示内置语言关键字,使用小写字母表示程序员定义的标识符。

注意以下5个字符:

& { } [ ]

虽然文字字符串中允许使用所有字符,但 Oracle 似乎并未在 PL/SQL 可见部分的任何地方使用这五个特定字符。 此外,没有直接的方法可以在程序员定义的标识符中使用这些字符。

其中许多字符(无论是单独的还是与其他字符组合)在 PL/SQL 中都具有特殊的意义。 下表列出了这些特殊符号。

符号描述
;分号:终止声明和语句
%百分号:属性指示符(游标属性如%ISOPEN和间接声明属性如%ROWTYPE); 也用作 LIKE 条件的通配符
_单下划线:LIKE条件下的单字符通配符
@At标志:远程定位指示器
:冒号:主机变量指示符,例如 Oracle Forms 中的 :block.item
< > 或 != 或 ^= or ~=不等于
||双竖线:连接运算符
<< 和>>标签分隔符
<= 和 >=小于或等于和大于或等于关系运算符
:=赋值运算符
=>位置符号的关联运算符
双点:范围运算符
/* 和 */开始和结束多行注释块分隔符

字符被组合成词汇单元,也称为语言的原子,因为它们是最小的单个组件。 PL/SQL 中的词法单元是以下任意一种:

  • 标识符
  • 文字
  • 分隔符
  • 注释

Identifiers

标识符是 PL/SQL 对象的名称,包括以下任意内容:

  • 常数或变量
  • 例外
  • 游标
  • 程序名称:过程、函数、包、对象类型、触发器等。
  • 保留字
  • 标签

PL/SQL 标识符的默认属性总结如下:

  • 长度最多 30 个字符
  • 必须以字母开头
  • 可以包含 $(美元符号)、_(下划线)和 #(井号)
  • 不能包含任何“空白”字符
  • 不区分大小写

标识符是程序中对象的句柄,也是与其他程序员通信的主要方式之一。 因此,许多组织采用命名约定。 即使没有命名约定的要求,您仍然需要仔细选择变量名称…即使您是唯一会看到代码的人!

尽管在实践中很少这样做,但实际上您可以通过用双引号将标识符括起来来打破其中一些规则(不推荐)。

您可能需要在 SQL 语句中使用双引号技巧来引用大小写混合名称存在的数据库对象。 当程序员使用 Microsoft Access 创建 Oracle 表时,我就见过这种情况。

Reserved Words

PL/SQL 提供两种内置标识符:

  • 保留字(如BEGIN,END)
  • STANDARD 包中的标识符

在这两种情况下,您不应该(而且在许多情况下不能)重新定义标识符以供程序自己使用。

Reserved words

PL/SQL 编译器保留某些标识符仅供其使用。 换句话说,您不能使用该标识符的名称来声明变量。 这些称为保留字。 例如,你不能声明一个名为 end 的变量。

Identifiers from STANDARD package

除了避免使用与关键字重复的标识符之外,还应该避免使用实际上覆盖 Oracle 公司在名为 STANDARD 的特殊内置包中定义的名称的标识符。 STANDARD 是 PL/SQL 中的两个默认包之一; Oracle 在这个包中定义了 PL/SQL 语言的许多基本构建块,包括 PLS_INTEGER 等数据类型、DUP_VAL_ON_INDEX 等异常以及 UPPER、REPLACE 和 TO_DATE 等函数。

STANDARD(以及 DBMS_STANDARD,另一个默认包)中定义的标识符不是保留字。 您可以使用相同的名称声明自己的变量,并且您的代码将编译。 然而,如果你这样做,将会造成很多混乱。

STANDARD 包将在第 24 章中详细探讨。

How to avoid using reserved words

为您的标识符找到有效的名称应该是最不重要的问题,因为合法字符有成千上万的排列。 问题是:如何知道自己的程序中是否无意中使用了保留字? 首先,如果您尝试使用实际保留的标识符的名称,编译器会通知您。 如果您的好奇心迫使您进一步研究,您可以针对 V$RESERVED_WORDS 视图构建一个查询,然后尝试编译一个使用保留字作为标识符的动态构造的 PL/SQL 块。 我正是这么做的; 您可以在本书网站上的reserved_words.sql 文件中找到该脚本。 运行此脚本的输出位于reserved.txt 中。

-- 以下是19c的结果,和作者12c的结果是一致的
Reserved Word Analysis Summary
Total count in V$RESERVED_WORDS = 1733
Total number of reserved words = 118
Total number of non-reserved words = 1615Reserved Words in PL/SQL - Cannot Use as Identifiers
}
RETURN
CLOSE
START
MOD
...

一般来说,我建议您避免使用 Oracle 公司用作其自身技术一部分的任何词语。 更好的是,使用采用一致前缀和后缀的命名约定,实际上保证您不会遇到真正的 PL/SQL 保留字。

Whitespace and Keywords

标识符必须至少用一个空格或定界符分隔,但您可以在可以放置空格的地方添加额外的空格、换行符(换行符和/或回车符)和制表符来格式化文本,而不改变你代码的含义。
但是,您不能在词汇单元内放置空格、回车符或制表符,例如“不等于”符号 (!=)不能写成! =

Literals

文字是不由标识符表示的值; 它只是一个值。 以下是您可以在 PL/SQL 程序中看到的一些文字:

  • 数字。如123.45f(32位浮点数), 7D(64位浮点数)
  • 字符串。如’Hello, World’,q’!hello!’
  • 时间间隔。如INTERVAL ‘25-6’ YEAR TO MONTH, INTERVAL ‘-18’ MONTH, NULL
  • 布尔值。如TRUE,FALSE,NULL

字符串 q’!hello!'中, ! 是用户定义的分隔符,在 Oracle 数据库 10g 中引入; 前导的q 和两端的单引号告诉编译器 ! 是分隔符,而字符串就是单词 hello。

INTERVAL 数据类型允许您管理日期或时间戳之间的时间量。

与标识符不同,PL/SQL 中的字符串文字区分大小写。因此’Steven’和’steven’不相等。

NULLs

在 Oracle 数据库中,值的缺失由关键字 NULL 表示。 如上一节所示,几乎所有 PL/SQL 数据类型的变量都可以以 null 状态存在(此规则的例外是任何关联数组类型,其实例永远不会为 null)。 正确处理 NULL 变量对于程序员来说都是一个挑战,而且NULL字符串需要特殊考虑。

在 Oracle SQL 和 PL/SQL 中,空字符串通常与零字符的文字无法区分,字面上表示为’'(两个连续的单引号,中间没有字符)。 例如,以下表达式在 SQL 和 PL/SQL 中都将求值为 TRUE:

'' IS NULL

在 PL/SQL 中将零长度字符串分配给 VARCHAR2(n) 变量也会产生 NULL 结果:

DECLAREstr VARCHAR2(1) := '';
BEGINIF str IS NULL   -- will be TRUE

此行为与数据库对 VARCHAR2 表列的处理一致。

不过,让我们看看 CHAR 数据——它有点奇怪。 如果您在 PL/SQL 中创建 CHAR(n) 变量并为其分配零长度字符串,则数据库会用空格字符填充空变量,使其不为空:

DECLAREflag CHAR(2) := '';  -- try to assign zero-length string to CHAR(2)
BEGINIF flag = '  '   ...   -- will be TRUEIF flag IS NULL  ...   -- will be FALSE

奇怪的是,PL/SQL 是您会看到这种行为的唯一地方。 在数据库中,当您将零长度字符串插入到 CHAR(n) 表列中时,数据库不会将该列的内容填充为空白,而是将其保留为 NULL!

SQL> create table t1(a varchar2(16));Table created.SQL> insert into t1 values ('');1 row created.SQL> select count(*) from t1 where a is null;COUNT(*)
----------1SQL> insert into t1 values ("");
ERROR:
ORA-01741: illegal zero-length identifier

这些示例说明 Oracle 部分遵守 ANSI SQL 标准 92 和 99 版本,该标准强制要求零长度字符串和 NULL 字符串之间存在差异。 Oracle承认这种差异,并表示将来可能会完全采用该标准。 不过,该警告已经发出了大约 15 年,但目前还没有发生。

虽然 NULL 的行为就像其默认数据类型是 VARCHAR2,但数据库将尝试将 NULL 隐式转换为当前操作所需的任何类型。 有时,您可能需要使用 TO_NUMBER(NULL) 或 CAST(NULL AS NUMBER) 等语法进行显式转换。

Embedding Single Quotes Inside a Literal String

较麻烦的是,当您需要将分隔符本身放入字符串中时。 在 Oracle 数据库 10g 发布之前,如果您希望字符串中包含单引号,则可以在彼此旁边写入两个单引号。 下表提供了一些示例。
|文字(默认分隔符)|实际值|
|‘There’‘s no business like show business.’|‘There’s no business like show business.’|
|‘“Hound of the Baskervilles”’|Hound of the Baskervilles’|
|‘’‘’|‘|
|’‘‘hello’’‘|‘hello’|
|’‘’‘’‘|’'|

为了简化这种类型的构造,Oracle 数据库 10g 引入了用户定义的分隔符。 以“q”开头的文字来标记分隔符,并用单引号将分隔表达式括起来。

文字(突出显示分隔符)实际值
q’ ( There’s no business like show business.) ’There’s no business like show business.’
q’ { “Hound of the Baskervilles” } ’“Hound of the Baskervilles”
q’ [ ’ ] ’
q’ !‘hello’ ! ’‘hello’

还有,q'|''|'相当于''

如示例所示,您可以使用普通分隔符,例如 ! 或|,或者您可以使用**“配对”**分隔符,例如左括号、右括号、花括号和方括号。

最后一点:正如您所期望的,双引号字符在字符串文字中没有任何特殊意义。 它被视为与字母或数字相同。

Numeric Literals

数字文字可以是整数或实数(包含小数部分的数字)。 请注意,PL/SQL 认为数字 154.00 是 NUMBER 类型的实数,即使小数部分为零并且该数字实际上是整数。 在内部,整数和实数具有不同的表示形式,并且两者之间的转换有小的开销。

您还可以使用科学记数法来指定数字文字。 使用字母 E(大写或小写)将数字乘以 10 的 n 次方(例如 3.05E19、12e–5)。

从 Oracle Database 10g 开始,实数可以是 Oracle NUMBER 类型或 IEEE 754 标准浮点类型。 浮点文字可以是 BINARY(32 位;用尾随 F 指定)或 BINARY DOUBLE(64 位;用 D 指定)。

在某些表达式中,您可以按照 IEEE 标准的规定使用下表中的命名常量。

描述二进制浮点数(32 位)二进制双精度(64 位)
“不是数字”(NaN); 除以 0 或无效运算的结果BINARY_FLOAT_NANBINARY_DOUBLE_NAN
正无穷大BINARY_FLOAT_INFINITYBINARY_DOUBLE_INFINITY
可表示的绝对最大数BINARY_FLOAT_MAX_NORMALBINARY_DOUBLE_MAX_NORMAL
最小正常数; 下溢阈值BINARY_FLOAT_MIN_NORMALBINARY_DOUBLE_MIN_NORMAL
小于下溢阈值的最大正数BINARY_FLOAT_MAX_SUBNORMALBINARY_DOUBLE_MAX_SUBNORMAL
可表示的绝对最小正数BINARY_FLOAT_MIN_SUBNORMALBINARY_DOUBLE_MIN_SUBNORMAL

Boolean Literals

PL/SQL 提供了两种文字来表示布尔值:TRUE 和 FALSE。 这些值不是字符串; 你不应该在它们周围加上引号。

另一方面,在检查布尔表达式的值时不需要引用文字值。 相反,只需让该表达式不言而喻,如以下 IF 语句的条件子句所示:

DECLAREenough_money BOOLEAN;
BEGINIF enough_moneyTHEN...

布尔表达式、变量或常量也可能计算为 NULL,它既不是 TRUE 也不是 FALSE。 有关详细信息,请参阅第 4 章。

The Semicolon Delimiter

PL/SQL 程序由一系列声明和语句组成。 这些是逻辑上定义的,而不是物理上的。 换句话说,它们并不是以代码行的物理结尾结束;而是以分号 (😉 结尾。 事实上,一条语句通常分布在多行中以使其更具可读性。

仍然需要分号来终止每个逻辑可执行语句,即使它们相互嵌套。 除非您试图创建不可读的代码,否则我建议您不要将 IF 语句的不同组成部分组合在一行上。 我还建议您在每一行上放置不超过一个声明或声明。

Comments

内联文档(也称为注释)是优秀程序的重要元素。 虽然本书提供了许多关于如何通过良好的命名实践和模块化使程序自我记录的建议,但这些技术本身很少足以传达对复杂程序的透彻理解。

PL/SQL 提供两种不同的注释样式:单行注释和多行块注释。

Single-Line Comment Syntax

单行注释以两个连字符 (–) 开头,不能用空格或任何其他字符分隔。 双连字符之后到物理行末尾的所有文本都被视为注释,会被编译器忽略。 如果双连字符出现在行的开头,则整行都是注释。

Multiline Comment Syntax

虽然单行注释对于记录简短的代码或忽略当前不希望执行的行很有用,但多行注释更适合包含较长的注释块。

多行注释以斜杠星号 (/) 开头,以星号斜杠 (/) 结束。 PL/SQL 将这两个符号序列之间找到的所有字符视为注释的一部分,并且编译器会忽略它们。

以下多行注释示例显示了过程的标题部分。 我在左边距中使用垂直条,这样当眼睛向下移动到程序的左边缘时,它可以轻松地挑选出注释块:

PROCEDURE calc_revenue (company_id IN NUMBER) IS
/*
| Program: calc_revenue
| Author: Steven Feuerstein
| Change history:
|   10-JUN-2009 Incorporate new formulas
|   23-SEP-2008 - Program created
|*/
BEGIN...
END;

您还可以使用多行注释来屏蔽代码行以进行测试。

The PRAGMA Keyword

真正源自希腊语的编程概念是 pragma,它的意思是“行为”,或者隐含地是“动作”。 在各种编程语言中,编译指示通常是一行源代码,规定您希望编译器执行的操作。 这就像你给编译器的一个选项; 它可能会导致程序不同的运行时行为,但它不会直接转换为字节码。

PL/SQL 有一个 PRAGMA 关键字,其语法如下:

PRAGMA instruction_to_compiler;

PL/SQL 编译器将在声明部分的任何位置接受此类指令,但大多数指令对于放置都有某些附加要求。

PL/SQL 提供了多种编译指示:

  • AUTONOMOUS_TRANSACTION
    告诉 PL/SQL 运行时引擎提交或回滚当前块内对数据库所做的任何更改,而不影响主事务或外部事务。 更多信息请参见第 14 章。

  • EXCEPTION_INIT
    告诉编译器将特定的错误号与您在程序中声明为异常的标识符相关联。 必须遵循异常声明。 有关详细信息,请参阅第 6 章。

  • RESTRICT_REFERENCES
    告诉编译器打包程序的纯度级别(无副作用)。 更多信息请参见第 17 章。

  • SERIALLY_REUSABLE
    告诉 PL/SQL 运行时引擎包级数据不应在对该数据的引用之间保留。 更多信息请参见第 18 章。

以下块演示了如何使用 EXCEPTION_INIT 编译指示来命名内置异常,否则该异常只有一个数字:

DECLAREno_such_sequence EXCEPTION;PRAGMA EXCEPTION_INIT (no_such_sequence,2289);
BEGIN...
EXCEPTIONWHEN no_such_sequenceTHENq$error_manager.raise_error ('Sequence not defined');
END;

Labels

PL/SQL 标签是一种命名程序特定部分的方法。 从语法上来说,标签的格式如下:

<<identifier>>

这里identifier是一个有效的标识符,这里没有终止符。 标签直接出现在它们所标记的事物的前面,该事物必须是可执行语句 - 即使它只是 NULL 语句:

BEGIN...<<the_spot>>NULL;

因为匿名块本身就是可执行语句,所以标签可以在匿名块执行期间“命名”它。

为块添加标签的原因之一是提高代码的可读性。 当您给某些东西命名时,您就可以自行记录该代码。 您还澄清了自己对该代码应该做什么的想法,有时会找出过程中的错误。

使用块标签的另一个原因是允许您限定对封闭块中在当前嵌套块中具有重复名称的元素的引用。 当然,应尽量避免重名。

标签的第三个功能是充当 GOTO 语句的目标。 参见第 4 章中对 GOTO 的讨论。

尽管我见过或参与过的程序很少需要使用标签,但此功能的最后一个用途比前三个组合更重要:标签可以用作嵌套循环中 EXIT 语句的目标。

BEGIN<<outer_loop>>LOOPLOOPEXIT outer_loop;END LOOP;some_statement;END LOOP;
END;

生词

  • indispensable 必不可少,必须

相关文章:

Oracle PL/SQL Programming 第3章:Language Fundamentals 读书笔记

总的目录和进度&#xff0c;请参见开始读 Oracle PL/SQL Programming 第6版 每种语言&#xff08;无论是人类语言还是计算机语言&#xff09;都有语法、词汇和字符集。 为了使用该语言进行交流&#xff0c;您必须学习管理其使用的规则。 我们许多人对学习新的计算机语言持谨慎…...

【Spring Boot 3】【@Scheduled】动态修改定时任务时间

【Spring Boot 3】【@Scheduled】动态修改定时任务时间 背景介绍开发环境开发步骤及源码工程目录结构总结背景 软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习…...

WordPress如何自定义日期和时间格式?附PHP日期和时间格式字符串

WordPress网站在很多地方都需要用到日期和时间&#xff0c;那么我们应该在哪里设置日期和时间呢&#xff1f;又如何自定义日期和时间格式呢&#xff1f;下面boke112百科就跟大家一起来学习一下PHP标准化的日期和时间格式字符串。 特别说明&#xff1a;格式字符是标准化的&#…...

log4j2 配置入门介绍

配置 将日志请求插入到应用程序代码中需要进行大量的计划和工作。 观察表明&#xff0c;大约4%的代码专门用于日志记录。因此&#xff0c;即使是中等规模的应用程序也会在其代码中嵌入数千条日志记录语句。 考虑到它们的数量&#xff0c;必须管理这些日志语句&#xff0c;而…...

深入Pyecharts:桑基图绘制与炫酷效果实战【第38篇—python:桑基图】

文章目录 深入Pyecharts&#xff1a;桑基图绘制与炫酷效果实战桑基图简介安装 Pyecharts简单桑基图的绘制自定义桑基图的炫酷效果高级样式定制 多组数据桑基图的展示动态桑基图的绘制结合真实数据的桑基图案例导出和分享进阶应用&#xff1a;桑基图与其他图表的组合总结 深入Py…...

RBD —— 不同材质破碎

目录 Working with concrete Chipping Details Proxy geometry Constraints Working with glass Chipping Proxy geometry Constraints Resolving issues with glass fracturing Working with wood Clustering Using custom cutters Working with concrete Concr…...

MySql8的简单使用(1.模糊查询 2.group by 分组 having过滤 3.JSON字段的实践)

MySql8的简单使用&#xff08;1.模糊查询 2.group by 分组 having过滤 3.JSON字段的实践&#xff09; 一.like模糊查询、group by 分组 having 过滤 建表语句 create table student(id int PRIMARY KEY,name char(10),age int,sex char(5)); alter table student add height…...

数据监控-Prometheus/Grafana

一、数据监控Prometheus 1、什么是Prometheus Prometheus是由SoundCloud开源监控告警解决方案,从2012年开始编写代码,到2015年github上开源以来,吸引不少用户以及公司的使用。Prometheus作为新一代的开源解决方案,很多理念与Google SRE的运维之道不谋而合。 2、Promet…...

Compose | UI组件(三) | TextField() 输入框组件

文章目录 TextField() 简介TextField() 输入框例子TextField() 输入框添加装饰OutlinedTextField 边框样式输入框BasicTextField 输入框组件 总结 TextField() 简介 在 Compose 中&#xff0c;TextField() 组件表示文本输入框 ExperimentalMaterial3Api Composable fun TextF…...

组件冲突、data函数、组件通信

文章目录 1.组件的三大组成部分 - 注意点说明2.组件的样式冲突&#xff08;用 scoped 解决&#xff09;3.data是一个函数4.组件通信1.什么是组件通信&#xff1f;2.不同的组件关系 和 组件通信方案分类 5.prop详解prop 校验①类型校验②完整写法&#xff08;类型&#xff0c;非…...

【C++杂货铺】详解类和对象 [上]

博主&#xff1a;代码菌-CSDN博客 专栏&#xff1a;C杂货铺_代码菌的博客-CSDN博客 目录 &#x1f308;前言&#x1f308; &#x1f4c1; 面向对象语言的特性 &#x1f4c1; 类 &#x1f4c2; 概念 &#x1f4c2; 定义 &#x1f4c1; 访问限定符 &#x1f4c2;分类 &#x…...

Linux 驱动开发基础知识—— 驱动设计的思想(六)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…...

Mybatis-Plus入门

Mybatis-Plus入门 MyBatis-Plus 官网&#xff1a;https://mp.baomidou.com/ 1、简介 MyBatis-Plus (简称 MP) 是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、 提高效率而生。 https://github.com/baomidou/mybatis-p…...

MODNet 剪枝再思考: 优化计算量的实验历程分享

目录 1 写在前面 2 模型分析 3 遇到问题 4 探索实验一 4.1 第一部分 4.2 第二部分 Error 1 Error 2 4.3 实验结果 ①参数量与计算量 ②模型大小 ③推理时延 5 探索实验二 5.1 LR Branch 5.2 HR Branch 5.2.1 初步分析 5.2.2 第一部分 enc2x 5.2.3 第二部分 en…...

Flink多流转换(1)—— 分流合流

目录 分流 代码示例 使用侧输出流 合流 联合&#xff08;Union&#xff09; 连接&#xff08;Connect&#xff09; 简单划分的话&#xff0c;多流转换可以分为“分流”和“合流”两大类 目前分流的操作一般是通过侧输出流&#xff08;side output&#xff09;来实现&…...

CSS高级技巧导读

1&#xff0c;精灵图 1.1 为什么需要精灵图&#xff1f; 目的&#xff1a;为了有效地减少服务器接收和发送请求的次数&#xff0c;提高页面的加载速度 核心原理&#xff1a;将网页中的一些小背景图像整合到一张大图中&#xff0c;这样服务器只需要一次请求就可以了 1.2 精灵…...

Redis数据类型-string

Redis-string类型 Redis中的数据类型全局命令get&setredis中变量设置的过期时间是如何检测的 keysexistsdelexpirettlpexpirepttltype string数据类型的底层的数据结构操作string类型的常用命令get&setmset&mgetsetnxsetexpsetexincr&decrincrby&decrbyinc…...

【HDFS】一天一个RPC系列--updatePipeline

updatePipeline这个RPC一般都会配合updateBlockForPipeline RPC一起使用。 先updateBlockForPipeline、然后再updatePipeline。 建议先阅读【HDFS】一天一个RPC系列–updateBlockForPipeline 本文目标是弄清楚以下问题: 弄清updatePipeline这个RPC的作用。弄清updatePipeli…...

CentOS 7 上使用 wget 安装 Nginx 并设置开机自启

在 CentOS 7 上使用 wget 安装 Nginx 并设置开机自启&#xff0c;你可以按照以下步骤进行操作&#xff1a; 首先&#xff0c;确保你已经以 root 用户或者具有 sudo 权限的用户身份登录到 CentOS 7。 安装 Nginx 所需的依赖包。在终端中运行以下命令&#xff1a; sudo yum inst…...

Android源码设计模式解析与实战第2版笔记(一)

第一章 走向灵活软件之路 — 面向对象的六大原则 优化代码的第一步 — 单一职责原则 单一职责原则的英文名称是Single Responsibility Principle&#xff0c;缩写是SRP。 SRP&#xff1a;就一个类而言&#xff0c;应该仅有一个引起它变化的原因。 一个类中应该是一组相关性很…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...