2. PL/SQL概述
PL/SQL 是 SQL 的 KingbaseES 过程扩展,是一种可移植的高性能事务处理语言。本概述解释了它的优点并简要描述了它的主要特性和架构。
2.1. PL/SQL的优势
PL/SQL 提供了优于其他编程语言的几个优点。 PL/SQL 具有以下优点:
2.1.1. 与SQL的紧密集成
PL/SQL 与使用最广泛的数据库操作语言 SQL 紧密集成。
例如:
-
PL/SQL 允许您使用所有 SQL 数据操作、游标控制和事务控制语句,以及所有 SQL 函数、运算符和伪列。
-
PL/SQL 完全支持 SQL 数据类型。
您无需在 PL/SQL 和 SQL 数据类型之间进行转换。例如,如果您的 PL/SQL 程序从 SQL 类型 VARCHAR2 的列中检索一个值,它可以将该值存储在 VARCHAR2 类型的 PL/SQL 变量中。
您可以为 PL/SQL 数据项指定数据库表的列或行的数据类型,而无需显式指定该数据类型(请参阅“使用 %TYPE 属性”和“使用 %ROWTYPE 属性”)。
-
PL/SQL 允许您运行 SQL 查询并一次处理一个结果集的行(请参阅“一次处理一个查询结果集”)。
-
PL/SQL 函数可以在SQL SELECT语句的WITH子句中声明和定义(请参阅 SQL 语言参考)。
PL/SQL 支持静态和动态 SQL。静态 SQL是其全文在编译时已知的 SQL。动态 SQL是直到运行时才知道全文的 SQL。动态 SQL 使您的应用程序更加灵活和通用。
另请参阅:
PL/SQL 静态 SQL 和 PL/SQL 动态 SQL 获取详细信息。
2.1.2. 高性能
PL/SQL 允许您将语句块发送到数据库,从而显着减少应用程序和数据库之间的流量。
-
绑定变量
当您在 PL/SQL 代码中直接嵌入 SQL 的 INSERT、UPDATE、DELETE、MERGE 或 SELECT 语句时,PL/SQL 编译器会将 WHERE 和 VALUES 子句中的变量转换为绑定变量(有关详细信息,请参阅“静态 SQL 语句中的名称解析”)。
KingbaseES 数据库可以在每次运行相同的代码时重用这些 SQL 语句,从而提高性能。
当您使用动态 SQL 时,PL/SQL 不会自动创建绑定变量,但是您可以通过显式指定它们来将它们与动态 SQL 一起使用(有关详细信息,请参阅“ EXECUTE IMMEDIATE 语句”)。
-
子程序
PL/SQL 子程序以明文的形式存储。每个session在第一次调用子程序都需要进行一次编译,且保存编译结果。需要注意的是,每个Seesion只缓存128个子程序的结果,超过128个子程序被调用,新调用的子程序的编译结果会覆盖旧的子程序编译结果。
2.1.3. 高生产力
PL/SQL 有许多节省设计和调试时间的特性,而且在所有环境中都是一样的。
PL/SQL 允许您编写紧凑的代码来操作数据。就像 PERL 这样的脚本语言可以读取、转换和写入文件中的数据一样,PL/SQL 可以查询、转换和更新数据库中的数据。
如果您学会将 PL/SQL 与一种工具一起使用,则可以将您的知识转移到其他工具上。有关 PL/SQL 特性的概述,请参阅“ PL/SQL 的主要特性”。
2.1.4. 可移植性
PL/SQL 是用于数据库开发的可移植标准语言。
您可以在运行数据库的任何操作系统和平台上运行 PL/SQL 应用程序。
2.1.5. 可扩展性
PL/SQL 存储子程序通过将应用程序处理集中在数据库服务器上来提高可伸缩性。有关子程序的更多信息,请参阅“子程序”
2.1.6. 可管理性
PL/SQL 存储的子程序提高了可管理性,因为您可以在数据库服务器上只维护一个子程序的副本,所有的客户端的缓存结果都是通过这一个副本生成。
任何的应用程序都可以使用子程序,您可以更改子程序而不影响调用它们的应用程序。有关子程序的更多信息,请参阅“子程序”。
2.1.7. 支持面向对象编程
PL/SQL 允许定义可用于面向对象设计的对象类型。
PL/SQL 支持带有“抽象数据类型”的面向对象编程。
2.2. PL/SQL的主要特点
PL/SQL 结合了 SQL 的数据操作能力和过程语言的处理能力。
当使用 SQL 解决问题时,也可以从 PL/SQL 程序执行 SQL 语句,而无需学习新的 API。
与其他过程编程语言一样,PL/SQL 允许您声明常量和变量、控制程序流、定义子程序和捕获运行时错误。
您可以将复杂的问题分解为易于理解的子程序,您可以在不同的应用程序中重复使用这些子程序。
2.2.1. 错误处理
PL/SQL 使检测和处理错误变得容易。
发生错误时,PL/SQL 会引发异常。 正常执行停止并将控制转移到 PL/SQL 块的异常处理部分。 您不必像在 C 程序中那样检查每个操作以确保其成功。
有关详细信息,请参阅 PL/SQL 错误处理 。
2.2.2. 块
PL/SQL 源程序的基本单元是块,它对相关的声明和语句进行分组。
PL/SQL 块由关键字 DECLARE、BEGIN、EXCEPTION 和 END 定义。这些关键字将块分为声明部分、可执行部分和异常处理部分。只有可执行部分是必需的。一个块可以有一个标签。
标签对块来说是局部区域的别名,并且在块完成执行时不再存在,有助于避免变量和子程序的命名空间混乱。
块可以嵌套:因为块是可执行语句,所以它可以出现在另一个块中,只要允许可执行语句。
您可以将块提交到交互式工具或将其嵌入到 KingbaseES 预编译器或OCI程序中。交互式工具或程序运行该块一次。该块不存储在数据库中,因此,它被称为匿名块(即使它有标签)。
匿名块每次加载到内存时都会被编译一次,它的编译分为三个阶段:
-
语法检查:检查 PL/SQL 语法,并生成解析树。
-
语义检查:对解析树进行类型检查和进一步处理。
-
代码生成:生成PL/SQL能识别的执行树
有关语法的详细信息,请参阅“块”。
示例 2-1 PL/SQL 块结构
此示例显示 PL/SQL 块的基本结构。
DECLARE -- Declarative part (optional) -- Declarations of local types, variables, & subprograms BEGIN -- Executable part (required) -- Statements (which can use items declared in declarative part) [EXCEPTION -- Exception-handling part (optional) -- Exception handlers for exceptions (errors) raised in executable part] END;
2.2.3. 变量和常量
PL/SQL 允许您声明变量和常量,然后在可以使用表达式的任何地方使用它们。
随着程序的运行,变量的值可以改变,但常量的值不能。有关详细信息,请参阅“声明”和“为变量赋值”。
2.2.4. 子程序
PL/SQL子程序是一个命名的 PL/SQL 块,可以重复调用。
如果子程序有参数,则每次调用时它们的值可能不同。PL/SQL有两种类型的子程序,过程和函数。一个函数返回一个结果。
有关 PL/SQL 子程序的更多信息,请参阅PL/SQL 子程序。
2.2.5. 包
包是一个模式对象,它对逻辑相关的 PL/SQL 类型、变量、常量、子程序、游标和异常进行分组。
一个包被存储在数据库中,许多应用程序可以访问并使用它的内容。您可以将包视为应用程序。
您可以编写自己的包——有关详细信息,请参阅:ref:` PL/SQL 包`。您还可以使用 KingbaseES 数据库提供的许多特定产品的包。有关这些信息,请参阅 KingbaseES插件参考手册 。
2.2.6. 触发器
触发器是一个命名的 PL/SQL 单元,它存储在数据库中并响应数据库中发生的事件而运行。
您可以指定触发器是在事件之前还是之后触发,以及触发器是针对每个事件还是针对受事件影响的每一行运行。例如,您可以创建每次INSERT语句影响STUDENT表时运行的触发器。
有关触发器的更多信息,请参阅PL/SQL 触发器。
2.2.7. 输入和输出
大多数 PL/SQL 输入和输出 (I/O) 都是通过将数据存储在数据库表中或查询这些表的 SQL 语句完成的。所有其他 PL/SQL I/O 都是使用 KingbaseES 数据库提供的 PL/SQL 包完成的。
包 | 描述 |
---|---|
dbms_output | 允许PLSQL块、子程序、包和触发器进行显示输出。 |
UTL_FILE | 允许程序读写操作系统文件 |
2.2.8. 数据抽象
通过数据抽象可以处理数据的基本属性,而无需过多地关注细节。
你可以先设计一个数据结构,然后再设计操作它的算法。
2.2.8.1. 游标
游标是指向私有 SQL 区域的指针,该区域存储有关处理特定 SQL 语句或 PL/SQL SELECT INTO语句的信息。
您可以使用游标一次检索一行的结果集。您可以使用游标属性来获取有关游标状态的信息——例如,到目前为止该语句影响了多少行。
有关游标的更多信息,请参阅“游标概述”。
2.2.8.2. 复合变量
复合变量具有内部组件,您可以单独访问这些组件。
您可以将整个复合变量作为参数传递给子程序。PL/SQL 有两种复合变量:集合和记录。
在集合中,内部组件始终具有相同的数据类型,称为元素。您可以通过其唯一索引访问每个元素。Lists 和 arrays 是集合的经典示例。
在记录中,内部组件可以是不同的数据类型,称为字段。您可以通过名称访问每个字段。记录变量可以保存表格行或表格行中的某些列。
有关复合变量的更多信息,请参阅PL/SQL 集合和记录。
2.2.8.3. 使用 %ROWTYPE 属性
%ROWTYPE 属性允许您声明表示数据库表或视图的完整或部分行的记录。
对于整行或部分行的每一列,记录都有一个具有相同名称和数据类型的字段。如果行的结构发生变化,那么记录的结构也会相应地发生变化。
有关 %ROWTYPE 语法和语义的详细信息,请参阅“ %ROWTYPE 属性”。
有关其用法的更多详细信息,请参阅“使用 %ROWTYPE 属性声明项目”。
2.2.8.4. 使用 %TYPE 属性
%TYPE 属性允许您在不知道数据类型的情况下声明与先前声明的变量或列具有相同数据类型的数据项。
如果被引用项的声明发生变化,那么引用项的声明也会相应改变。%TYPE属性在声明变量以保存数据库值时特别有用。
有关 %TYPE 语法和语义的详细信息,请参阅“ %TYPE 属性”。
有关其用法的更多详细信息,请参阅“使用 %TYPE 属性声明项目”。
2.2.8.5. 抽象数据类型
抽象数据类型 (ADT)由数据结构和操作数据的子程序组成 。
构成数据结构的变量称为属性。操纵属性的子程序称为方法。
ADT存储在数据库中。ADT的实例可以存储在表中并用作PL/SQL变量。
ADT让您可以通过将大型系统分成可以重用的逻辑组件来降低复杂性。
有关 ADT 的更多信息,请参阅“ CREATE TYPE 语句”。
注意
ADT 也称为用户定义类型和对象类型。
2.2.9. 控制语句
控制语句是 SQL 最重要的 PL/SQL 扩展。
PL/SQL 有三类控制语句:
-
条件选择语句,可让您针对不同的数据值运行不同的语句。
有关详细信息,请参阅“条件选择语句”。
-
循环语句,可让您使用一系列不同的数据值重复相同的语句。
有关详细信息,请参阅“ LOOP 语句”。
-
顺序控制语句,允许您转到指定的、标记的语句,或者什么都不做。
有关详细信息,请参阅“顺序控制语句”。
2.2.10. 一次处理一行查询结果集
PL/SQL 允许您发出 SQL 查询并一次处理结果集的行。
您可以使用基本循环,也可以通过使用单独的语句来运行查询、检索结果并完成处理来精确控制过程。
示例 2-2 一次处理一个查询结果行
此示例使用基本循环。
CREATE TABLE stduent(name text, score number); insert into stduent values ('xiaoming', 85.5),('xiaozhang', 89),('xiaohong', 92); \set SQLTERM / BEGIN FOR student IN (SELECT * FROM stduent WHERE score > 90) LOOP raise notice 'student: %', student; END LOOP; END; /
结果:
NOTICE: student: (xiaohong,92) ANONYMOUS BLOCK
2.3. PL/SQL的架构
对 PL/SQL 体系结构的基本了解对 PL/SQL 程序员很有帮助。
2.3.1. PL/SQL 引擎
PL/SQL 编译和运行系统是一个编译和运行 PL/SQL 单元的引擎。
该引擎可以安装在数据库中或应用程序开发工具中。
在任一环境中,PL/SQL 引擎都接受任何有效的 PL/SQL 单元作为输入。引擎运行程序语句,但将SQL语句发送到数据库中的SQL引擎。
通常,数据库处理 PL/SQL 单元。
当应用程序开发工具处理 PL/SQL 单元时,它会将它们传递给其本地 PL/SQL 引擎。如果 PL/SQL 单元不包含 SQL 语句,则本地引擎处理整个 PL/SQL 单元。如果应用程序开发工具可以从条件和迭代控制中受益,这将非常有用。
2.3.2. PL/SQL 单元和编译参数
PL/SQL 单元受 PL/SQL 编译参数(一类数据库初始化参数)的影响。不同的 PL/SQL 单元——例如,包规范及其主体——可以有不同的编译参数设置。
PL/SQL 单元是以下之一:
-
PL/SQL anonymous block
-
FUNCTION
-
PACKAGE
-
PACKAGE BODY
-
PROCEDURE
-
TRIGGER
-
TYPE
-
TYPE BODY
参数 | 描述 |
---|---|
VARIABLE_CONFLICT | 变量名和列名冲突时,如何处理: PLSQL_RESOLVE_ERROR -- 报错, PLSQL_RESOLVE_VARIABLE -- 解析成变量名(默认), PLSQL_RESOLVE_COLUMN -- 解析成列名 |
PLSQL_CHECK_ASSERTS | 是否执行assert检查语句: false -- 不执行(默认), true -- 执行 |
ORA_OPEN_CURSORS | DBMS_SQL中允许打开的游标数,最大65535,最小值0, 默认值是300 |
COMPILE_CHECKS | 是否启用编译检查 false -- 不启用(默认), true -- 启用 |