PL/SQL 变量范围和内部外部块:嵌套结构

⚡ 智能摘要

PL/SQL 中的嵌套代码块可以将一个代码块放置在另一个代码块内部,从而分离复杂的逻辑并隔离异常处理。了解外部代码块和内部代码块之间的变量作用域,并使用代码块标签,可以避免同名变量产生歧义。

  • 🧱 嵌套块: 嵌套块是指放置在另一个块的执行部分或异常部分内的 PL/SQL 块。
  • 🌳 外层和内层: 一个外部(或父)块可以包含多个内部(或子)块,每个内部块都是一个完整的 PL/SQL 块。
  • 👁️ 变量作用域: 在内部代码块之前声明的外部代码块变量在内部代码块内可见,但内部代码块变量在外部不可见。
  • 🏷️ 模块标签: 给外部代码块贴标签,可以让内部代码块引用同名的外部变量,即 label.variable_name。
  • 🛡️ 异常隔离: 嵌套允许每个代码块处理自己的异常,保持ping 在引发错误的代码附近进行错误处理。
  • 🤖 人工智能协助: GitHub Copilot 等 AI 助手会草拟标记嵌套代码块并标记变量作用域冲突。

PL/SQL 变量在嵌套的内部和外部块中的作用域

什么是嵌套块 Oracle?

In PL / SQL每个代码块都可以嵌套在另一个代码块中。这样的代码块被称为嵌套代码块。当需要在保持代码块完整性的同时执行特定操作时,嵌套代码块非常常见。ping 该过程的代码位于单独的容器(代码块)中。

嵌套块的概念通过将复杂的逻辑拆分成单独的块,帮助程序员提高代码的可读性,并且它允许…… 例外 每个块都要在主外部块内进行处理。

嵌套块结构

一个代码块可以嵌套在另一个代码块中。它可以嵌套在执行部分或异常处理部分,并且这些代码块也可以被标记。一个外部代码块可以包含多个内部代码块。每个内部代码块本身也是一个 PL/SQL 块因此,内部代码块的所有属性和特征都与外部代码块相同。父代码块是主代码块,子代码块是嵌套代码块。

下图以图形方式表示了嵌套块结构,其中父块是主块,子块是嵌套块。

PL/SQL 嵌套块的图示,包含一个父级外块和一个子级内块

以下是嵌套代码块的语法。下面的屏幕截图显示了嵌套代码块的语法,并标注了外部代码块和内部代码块。

嵌套块语法,显示了带标签的外部块和内部块,每个块都包含 DECLARE、BEGIN 和 EXCEPTION 部分。

嵌套块语法

<<outer_block>>
DECLARE
 <Declarative section> 
BEGIN
 <Execution part for outer block begins>

 <<inner block>>
 DECLARE
  <Declarative section>
 BEGIN
  <Execution part for inner block>.
 EXCEPTION 
  <Exception handling part>
 END;

 <Execution part for outer block begins> 
EXCEPTION 
<Exception handling part>
END;
  • 上面的语法显示了一个嵌套块,其中总共包含两个块。
  • 这些块被标记为“outer_block”和“inner_block”。

嵌套块中的作用域:变量作用域

在嵌套代码块中,使用每个代码块之前,需要清楚地了解其作用域和可见性。尤其是在内层代码块中,内外层代码块的元素都是可见的,因此必须对此有透彻的理解。

以下几点总结了嵌套块中的作用域。

  • 外部代码块中声明的元素,以及在内部代码块定义之前定义的值,在内部代码块中是可见的。
  • 内部代码块中声明的元素在外部代码块中不可见,它们仅在内部代码块内可见。
  • 外块和内块可以有 变量 同名。
  • 对于同名变量,内部代码块默认只引用内部代码块中声明的变量。
  • 如果内部代码块想要引用与内部代码块变量同名的外部代码块变量,则必须给外部代码块添加标签,并且外部代码块变量可以这样引用: 。 '。

下面的例子可以帮助你更好地理解这些作用域。

例如1: 在这个例子中,我们可以看到内部代码块和外部代码块中变量的作用域。我们还可以看到如何使用代码块标签来引用这些变量。

下面截图显示了示例 1,其中内部块使用块标签引用外部块变量。

嵌套代码块中变量作用域的示例,通过代码块标签引用外部代码块变量

<<OUTER_BLOCK>>
DECLARE
var1 VARCHAR2(30):='outer_block';
var2 VARCHAR2(30):='value before inner block';
BEGIN
<<INNER_BLOCK>>
DECLARE
var1 VARCHAR2(30):='inner_block';
BEGIN
dbms_output.put_line(var1);
dbms_output.put_line(OUTER_BLOCK.var1); 
dbms_output.put_line(var2);
END;
var2:='value after inner block';
END;
/

Code 说明:

  • Code 第1行: 将外部块标记为“OUTER_BLOCK”。
  • Code 第3行: 声明变量“var1”为 VARCHAR2 (30),初始值为“outer_block”。
  • Code 第4行: 声明变量“var2”为 VARCHAR2 (30),初始值为“内部块之前的值”。
  • Code 第6行: 将内部块标记为“INNER_BLOCK”。
  • Code 第8行: 在内部块中声明变量“var1”,类型为 VARCHAR2 (30),初始值为“inner_block”。
  • Code 第10行: 打印'var1'的值。由于没有指定标签,默认情况下会从内部块中获取值,因此会打印'inner_block'消息。
  • Code 第11行: 打印外部代码块变量“var1”的值。由于内部代码块中有一个同名变量,我们引用外部代码块的标签。因此,它会打印“outer_block”消息。
  • Code 第12行: 打印外部代码块变量“var2”的值。由于内部代码块中没有同名变量,因此默认情况下会从外部代码块获取值,从而打印出“内部代码块之前的值”消息。
  • 外部代码块中的变量“var2”被赋值为“内部代码块之后的值”。但是,这个赋值发生在内部代码块定义之后,因此该值在内部代码块中并不存在。

例如2: 在这个例子中,我们计算两个数字之间的差值,一个数字声明在外层代码块中,另一个数字声明在内层代码块中。这两个数字具有相同的名称。让我们看看代码块标签是如何用于引用这些变量的。

下面截图显示了示例 2,它计算同名外部块变量和内部块变量之间的差异。

示例:使用块标签计算同名外部块变量和内部块变量之间的差异

<<OUTER_BLOCK>>
DECLARE 
ln_val NUMBER :=5;
BEGIN
<<INNER_BLOCK>>
DECLARE 
ln_val NUMBER :=3;
BEGIN
dbms_output.put_line('The difference between outer block and inner block variable is:'||outer_block.ln_val-inner_block.ln_val);
END;
END;
/

Code 说明:

  • Code 第1行: 将外部块标记为“OUTER_BLOCK”。
  • Code 第3行: 声明变量“ln_val”为NUMBER类型,初始值为“5”。
  • Code 第5行: 将内部块标记为“INNER_BLOCK”。
  • Code 第7行: 在内部代码块中声明变量“ln_val”,类型为NUMBER,初始值为“3”。
  • Code 第9行: 打印外部代码块和内部代码块中 'ln_val' 值的差值。 。使用“格式”来引用这些变量,以避免因变量名相同而导致的冲突。

常见问题

嵌套代码块是指放置在另一个代码块内部的匿名代码块,它会在出现的位置以内联方式运行。 子程序 (过程或函数)是一个已命名的、可重用的单元,它单独存储,并按名称调用,还可以选择带参数。

每个代码块都可以有自己的异常处理部分。内部代码块中引发的异常首先由该代码块处理;如果未被处理,则会传播到包含它的外部代码块的处理程序。这样,就可以将错误处理隔离到每个代码块中。

PL/SQL 没有设置嵌套层数的限制,因此代码块可以嵌套很多层。但实际上,嵌套过深会降低代码的可读性,所以大多数代码都只嵌套两到三层,并将可重用的逻辑移到子程序中。

代码块标签(写在 DECLARE 语句前的双尖括号内)用于命名代码块。标签允许内部代码使用 `label.variable_name` 来限定外部变量,还可以作为 GOTO 指令的目标,从而使嵌套代码更易于阅读和编写文档。

是的。嵌套代码块可以出现在任何允许执行语句的地方,包括循环、IF 分支语句或过程体内部。这样,您可以将声明和异常处理限定在需要它们的代码部分。

嵌套主要是一种编译时结构化工具,本身不会增加明显的运行时开销。它能提高代码的可读性和错误隔离性。过深的嵌套主要影响的是代码的可维护性,而不是速度。

是的。 GitHub 副驾驶 根据注释,草稿中标注了外部和内部块,包括 DECLARE、BEGIN 和 EXCEPTION 部分。 Rev查看代码块标签和变量作用域,以便同名的内部变量和外部变量能够按预期解析。

AI 助手会分析嵌套代码块,并标记出被遮蔽的变量、不合格的引用以及超出作用域的访问。这种机器学习审查会突出显示内部代码块在代码运行前悄悄使用同名错误变量的情况。

总结一下这篇文章: