C语言开发过程中,需要对数据库进行操作,使用 Oracle 数据库一般会采用Oracle Pro*C/C++ 预编译器。
本文章参考Oracle官方文档和自我实践,实验环境为 RHEL7 和 Oracle19c,详细介绍 Oracle Pro*C/C++ 预编译器,了解它在开发操作 Oracle 数据的应用程序中的作用,并了解它使您的应用程序能够做什么,具体如使用。
本章介绍Oracle Pro*C/C++嵌入式SQL语句。
嵌入式 SQL介绍
嵌入式 SQL是指放置在应用程序中的 SQL 语句。
因为它包含 SQL 语句,所以应用程序称为宿主程序,编写它的语言称为宿主语言。
例如,Pro*C/C++ 提供了在 C 或 C++ 主机程序中嵌入某些 SQL 语句的能力。
要操作和查询 Oracle 数据,您可以使用 INSERT、UPDATE、DELETE 和 SELECT 语句。
INSERT 向数据库表添加数据行,UPDATE 修改行,DELETE 删除不需要的行,SELECT 检索满足搜索条件的行。
强大的 SET ROLE 语句可让您动态管理数据库权限。一个角色是相关的系统和对象权限,或者授予用户或其他角色命名组相关的系统或对象权限的命名组。角色定义存储在 Oracle 数据字典中。您的应用程序可以根据需要使用 SET ROLE 语句来启用和禁用角色。
嵌入式 SQL分类
嵌入式 SQL 包括所有交互式 SQL 语句以及其他允许您在 Oracle 和主机程序之间传输数据的语句。
有两种类型的嵌入式 SQL 语句:可执行语句和指令。
- 可执行语句 可执行语句调用运行时库 SQLLIB,可以使用它们连接到 Oracle,定义、查询和操作 Oracle 数据,控制对 Oracle 数据的访问,以及处理事务,可以放置在任何可以放置 C 或 C++ 语言可执行语句的地方。
| 可执行语句 | 说明 |
|---|---|
| ALLOCATE | 定义和控制 Oracle 数据 |
| ALTER | |
| ANALYZE | |
| DELETE | DML语句 |
| INSERT | |
| SELECT | |
| UPDATE | |
| COMMIT | 提交事务 |
| ROLLBACK | |
| SAVEPOINT | |
| SET TRANSACTION | |
| DESCRIBE | 使用动态 SQL |
| EXECUTE | |
| PREPARE | |
| ALTER SESSION | 控制会话 |
| SET ROLE |
- 指令 指令不会调用 SQLLIB 并且不会对 Oracle 数据进行操作。可以使用指令来声明 Oracle 对象、通信区域和 SQL 变量,可以放在任何可以放置 C 或 C++ 变量声明的地方。
| 指令 | 说明 |
|---|---|
| ARRAYLEN | 定义和控制 Oracle 数据 |
| BEGIN DECLARE SECTION | 声明宿主变量开始 |
| END DECLARE SECTION | 声明宿主变量结束 |
| DECLARE | 声明 Oracle 用户对象 |
| INCLUDE | 复制文件 |
| TYPE | 等效数据类型 |
| VAR | 等价变量 |
| WHENEVER | 处理运行时错误 |
嵌入式 SQL 语法
在应用程序中,可以自由地将完整的 SQL 语句与完整的 C 语句混合使用,并在 SQL 语句中使用 C 变量或结构。将 SQL 语句构建到宿主程序中的唯一特殊要求是它们以关键字 EXEC SQL 开始并以分号结束。
Pro*C/C++ 将所有 EXEC SQL 语句转换为对运行时库 SQLLIB 的调用。
/* 嵌入式 ROLLBACK 语句 */
EXEC SQL ROLLBACK;
宿主和指标变量
主机变量是 Oracle 和程序之间通信的关键。主机变量是一个标量或集合变量用C语言声明和使用Oracle共享,这意味着这两个程序和Oracle可以引用它的值。
程序使用输入主机变量将数据传递给 Oracle。Oracle 使用输出主机变量将数据和状态信息传递给程序。程序为输入的宿主变量赋值;Oracle 为输出主机变量赋值。
可以使用 SQL 表达式的任何地方都可以使用宿主变量。在 SQL 语句中,宿主变量必须以冒号 (:) 为前缀,以将它们与 SQL 关键字区分开来。
还可以使用C语言结构来包含许多主机变量。当您在嵌入式 SQL 语句中命名结构时,以冒号为前缀,Oracle 使用结构的每个组件作为主变量。
在 SQL 语句中,指示符变量必须以冒号 (:) 为前缀,并紧跟在其关联的主变量之后。关键字 INDICATOR 可以放在主变量和它的指示器之间,以增加清晰度。
如果宿主变量被封装在一个结构体中,并且想使用指示变量,只需为宿主结构中的每个宿主变量创建一个具有指示变量的结构体,并在 SQL 语句中命名指示结构体,紧跟在主变量结构,并以冒号为前缀。您还可以使用 INDICATOR 关键字来分隔宿主结构及其关联的指标结构。
Oracle 数据类型
通常,主机程序向 Oracle 输入数据,Oracle 向程序输出数据。Oracle 将输入数据存储在数据库表中,并将输出数据存储在程序主变量中。要存储数据项,Oracle 必须知道其数据类型,它指定存储格式和有效值范围。
Oracle 识别两种数据类型:内部和外部。内部数据类型指定 Oracle 如何在数据库列中存储数据。Oracle 还使用内部数据类型来表示数据库伪列,这些伪列返回特定的数据项但不是表中的实际列。
外部数据类型指定数据如何存储在宿主变量中。当您的主机程序向 Oracle 输入数据时,如有必要,Oracle 会在输入主机变量的外部数据类型和目标数据库列的内部数据类型之间进行转换。当 Oracle 向宿主程序输出数据时,如有必要,Oracle 会在源数据库列的内部数据类型和输出宿主变量的外部数据类型之间进行转换。
数组
Pro*C/C++ 允许您定义数组宿主变量(称为宿主数组)和结构数组,并使用单个 SQL 语句对它们进行操作。使用数组 SELECT、FETCH、DELETE、INSERT 和 UPDATE 语句,您可以轻松查询和操作大量数据。您还可以在宿主变量struct 中使用宿主数组。
数据类型等效
Pro*C/C++ 通过让您对等数据类型增加应用程序的灵活性。这意味着可以自定义 Oracle 解释输入数据和格式化输出数据的方式。
在逐个变量的基础上,可以将支持的 C 数据类型等同于 Oracle 外部数据类型,还可以将用户定义的数据类型等同于 Oracle 外部数据类型。
私有 SQL 区域、游标和活动集
为了处理 SQL 语句,Oracle 使用称为私有 SQL 区的工作区。私有 SQL 区存储执行 SQL 语句所需的信息。称为游标的标识符可让您命名 SQL 语句,访问其私有 SQL 区域中的信息,并在一定程度上控制其处理。
对于静态 SQL 语句,有两种类型的游标:隐式和显式。Oracle 为所有数据定义和数据操作语句隐式声明了一个游标,包括只返回一行的 SELECT 语句(查询)。但是,对于返回多行的查询,要在第一行之后进行处理,您必须显式声明一个游标(或使用主机数组)。
返回的行集称为活动集;它的大小取决于有多少行满足查询搜索条件。您使用显式游标来标识当前正在处理的行,称为当前行。
参照返回到终端屏幕的行集,屏幕光标可以指向要处理的第一行,然后是下一行,依此类推。同样,显式游标“指向”活动集中的当前行,这允许您的程序一次处理一行。
事务
一个事务是一系列逻辑相关的SQL语句(例如,信贷一个银行账户和借记另一个两次更新),Oracle将其视为一个单元,使得由语句所带来的所有变化是由在同一时间永久或撤消.
自上次执行数据定义、COMMIT 或 ROLLBACK 语句后执行的所有数据操作语句构成当前事务。
为帮助确保数据库的一致性,Pro*C/C++ 允许您使用 COMMIT、ROLLBACK 和 SAVEPOINT 语句定义事务。
COMMIT 使当前事务期间所做的任何更改永久化。ROLLBACK 结束当前事务并撤消自事务开始以来所做的任何更改。SAVEPOINT 标记事务处理中的当前点;与 ROLLBACK 一起使用,它会撤消部分事务。
错误和警告
执行嵌入式 SQL 语句时,要么成功,要么失败,并可能导致错误或警告。您需要一种方法来处理这些结果。Pro*C/C++ 提供两种错误处理机制:SQL 通信区 (SQLCA) 和 WHENEVER 语句。
SQLCA 是在主机程序中包含(或硬编码)的数据结构,定义了 Oracle 用来将运行时状态信息传递给程序的程序变量。使用 SQLCA,可以根据 Oracle 对刚刚尝试的工作的反馈采取不同的操作。例如,可以检查 DELETE 语句是否成功,如果成功,删除了多少行。
使用 WHENEVER 语句,您可以指定当 Oracle 检测到错误或警告条件时自动采取的操作。这些操作是:继续下一个语句、调用函数、分支到带标签的语句或停止。