Oracle Pro*C/C++ (九):嵌入式SQL游标

您所在的位置:网站首页 SQL游标使用的目的 Oracle Pro*C/C++ (九):嵌入式SQL游标

Oracle Pro*C/C++ (九):嵌入式SQL游标

2023-09-25 14:30| 来源: 网络整理| 查看: 265

C语言开发过程中,需要对数据库进行操作,使用 Oracle 数据库一般会采用Oracle Pro*C/C++ 预编译器。

本文章参考Oracle官方文档和自我实践,实验环境为 RHEL7 和 Oracle19c,详细介绍 Oracle Pro*C/C++ 预编译器,了解它在开发操作 Oracle 数据的应用程序中的作用,并了解它使您的应用程序能够做什么,具体如使用。

游标

当查询返回多行时,可以显式定义一个游标

查询返回的第一行以外的处理 跟踪当前正在处理的行

或者,您可以使用寄主数组。

游标标识查询返回的行集中的当前行。这允许您的程序一次处理一行。以下语句允许您定义和操作游标:

DECLARE CURSOR OPEN FETCH CLOSE

首先使用 DECLARE CURSOR 语句命名游标并将其与查询相关联。

OPEN 语句执行查询并标识所有满足查询搜索条件的行。这些行形成一个集合,称为游标的活动集。打开游标后,可以使用它来检索其关联查询返回的行。

活动集的行被一一检索(除非您使用主机阵列)。可以使用 FETCH 语句检索活动集中的当前行。可以重复执行 FETCH,直到检索到所有行。

从活动集中获取行后,可以使用 CLOSE 语句禁用游标,活动集将变为未定义。

以下部分将展示如何在应用程序中使用这些游标控制语句。

DECLARE CURSOR 语句

可以使用 DECLARE CURSOR 语句通过为游标命名并将其与查询相关联来定义游标,如以下示例所示:

EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, empno, sal FROM emp WHERE deptno = :dept_number;

游标名称是预编译器使用的标识符,而不是主机或程序变量,不应在声明部分中定义。因此,游标名称不能从一个预编译单元传递到另一个。游标名称不能连字符。它们可以是任意长度,但只有前 31 个字符有意义。为了与 ANSI 兼容,请使用不超过 18 个字符的游标名称。

提供了预编译器选项 CLOSE_ON_COMMIT 以在命令行或配置文件中使用。当 CLOSE_ON_COMMIT=YES 时,任何未用 WITH HOLD 子句声明的游标在 COMMIT 或 ROLLBACK 后关闭。

如果 MODE 指定的级别高于 CLOSE_ON_COMMIT,则 MODE 优先。默认值为 MODE=ORACLE 和 CLOSE_ON_COMMIT=NO。如果指定 MODE=ANSI,则任何未使用 WITH HOLD 子句的游标将在 COMMIT 时关闭。应用程序将运行得更慢,因为游标多次关闭并重新打开。当 MODE=ANSI 时设置 CLOSE_ON_COMMIT=NO 会提高性能。要查看 MODE 等宏选项如何影响 CLOSE_ON_COMMIT 等微选项

与游标关联的 SELECT 语句不能包含 INTO 子句。相反,INTO 子句和输出主变量列表是 FETCH 语句的一部分。

因为它是声明性的,所以 DECLARE CURSOR 语句必须在物理上(不仅仅是逻辑上)先于所有其他引用游标的 SQL 语句。也就是说,不允许向前引用游标。在以下示例中,OPEN 语句放错了位置:

... EXEC SQL OPEN emp_cursor; * -- MISPLACED OPEN STATEMENT EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, empno, sal FROM emp WHERE ename = :emp_name;

游标控制语句(DECLARE、OPEN、FETCH、CLOSE)必须都出现在同一个预编译单元中。例如,您不能在文件 A 中声明游标,然后在文件 B 中打开它。

您的宿主程序可以根据需要声明任意数量的游标。但是,在给定的文件中,每个 DECLARE 语句都必须是唯一的。也就是说,您不能在一个预编译单元中声明两个同名的游标,即使是跨块或过程,因为游标的范围在文件中是全局的。

对于 MODE=ANSI 或 CLOSE_ON_COMMIT=YES 的用户,可以在 DECLARE 部分中使用 WITH HOLD 子句来覆盖由两个选项定义的行为。设置这些选项后,行为将是在发出 COMMIT 时关闭所有游标。由于重新打开游标以继续处理的开销,这可能会影响性能。小心使用 WITH HOLD 可以加速需要在大多数方面符合 ANSI 预编译器标准的程序。

如果您将使用许多游标,您可能需要指定 MAXOPENCURSORS 选项。

OPEN 语句

您可以使用 OPEN 语句来执行查询并标识活动集。在以下示例中,您打开一个名为emp_cursor的游标:

EXEC SQL OPEN emp_cursor;

OPEN 将 SQLCA 中 SQLERRD 的第三个元素保存的行处理计数归零。但是,此时没有任何行对应用程序可见。这是由 FETCH 语句处理的。

OPEN 将光标定位在活动集的第一行之前。它还将 SQLCA 中 SQLERRD 的第三个元素保存的行处理计数归零。但是,此时实际上没有检索到任何行。这将由 FETCH 语句完成。

一旦您打开游标,在您重新打开游标之前,不会重新检查查询的输入主变量。因此,活动集不会改变。要更改活动集,您必须重新打开光标。

通常,您应该在重新打开游标之前关闭游标。但是,如果指定 MODE=ORACLE(默认值),则在重新打开游标之前不需要 CLOSE 游标。这可以提高性能。

OPEN 完成的工作量取决于三个预编译器选项的值:HOLD_CURSOR、RELEASE_CURSOR 和 MAXOPENCURSORS。

FETCH 语句

您可以使用 FETCH 语句从活动集中检索行并指定将包含结果的输出主变量。回想一下,与游标关联的 SELECT 语句不能包含 INTO 子句。相反,INTO 子句和输出主变量列表是 FETCH 语句的一部分。在以下示例中,您 FETCH INTO 三个主机变量:

EXEC SQL FETCH emp_cursor INTO :emp_name, :emp_number, :salary;

游标必须事先声明和打开。第一次执行 FETCH 时,光标从活动集中第一行之前移动到第一行。该行成为当前行。每次后续执行 FETCH 都会将游标前进到活动集中的下一行,从而更改当前行。光标只能在活动集中向前移动。要返回到已被 FETCH 取过的行,您必须重新打开游标,然后从活动集的第一行重新开始。

如果要更改活动集,必须为与游标关联的查询中的输入主变量分配新值,然后重新打开游标。当 MODE=ANSI 时,您必须在重新打开游标之前关闭游标。

如下一个示例所示,您可以使用不同的输出主变量集从同一个游标中 FETCH。但是,每个 FETCH 语句的 INTO 子句中对应的主变量必须具有相同的数据类型。

EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, Sal FROM emp WHERE deptno = 20; ... EXEC SQL OPEN emp_cursor; EXEC SQL WHENEVER NOT FOUND GOTO ... 为了 (;;) { EXEC SQL FETCH emp_cursor INTO :emp_name1, :salary1; EXEC SQL FETCH emp_cursor INTO :emp_name2, :salary2; EXEC SQL FETCH emp_cursor INTO :emp_name3, :salary3; ... }

如果活动集为空或不包含更多行,则 FETCH 将“未找到数据”错误代码返回到SQLCA 中的sqlcode,或者返回到 SQLCODE 或 SQLSTATE 状态变量。输出主变量的状态是不确定的。(在典型程序中,WHENEVER NOT FOUND 语句检测到此错误。)要重用游标,您必须重新打开它。

在以下情况下对游标进行 FETCH 是错误的:

在打开光标之前 在“未找到数据”条件之后 关闭后 CLOSE 语句

完成从活动集中提取行后,您关闭游标以释放通过打开游标获得的资源,例如存储。当游标关闭时,解析锁被释放。释放哪些资源取决于您如何指定 HOLD_CURSOR 和 RELEASE_CURSOR 选项。在以下示例中,您关闭名为emp_cursor的游标:

EXEC SQL CLOSE emp_cursor;

您不能从关闭的游标中 FETCH,因为它的活动集变得未定义。如有必要,您可以重新打开游标(例如,使用输入主变量的新值)。

当 MODE=ORACLE 时,发出 COMMIT 或 ROLLBACK 将关闭在 CURRENT OF 子句中引用的游标。其他游标不受 COMMIT 或 ROLLBACK 的影响,如果打开,则保持打开状态。但是,当 MODE=ANSI 时,发出 COMMIT 或 ROLLBACK 会关闭所有显式游标。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3