南大通用GBase8s 常用SQL语句(114)

使用 FOR READ ONLY 选项

使用 FOR READ ONLY 关键字可将游标定义为只读游标。声明为只读的游标不可以用于更新(或删除)任何它得到的行。

对 FOR READ ONLY 关键字的需要取决于数据库是符合 ANSI 的还是不符合 ANSI 。

因为在不兼容 ANSI 的数据库中,DECLARE 语句定义的游标在缺省情况下是只读游标,所以如果想将游标成为一个只读游标,您不需要指定 FOR READ ONLY 关键字。显式地指定 FOR READ ONLY 关键字的唯一好处是为了更好地编制程序文档。

在兼容 ANSI 的数据库中,如果 SELECT 语句符合与游标相关联的 SELECT 语句的子集 中列出的对更新游标的所有限制,那么通过 DECLARE 语句与 SELECT 语句相关联的游标在缺省情况下是一个更新游标。如果想让一个 Select 游标成为只读,则必须在声明该游标时使用 FOR READ ONLY 关键字。

数据库服务器可以针对只读游标使用比针对更新游标更为宽松的锁定。

下面的示例创建了一个只读游标:

EXEC SQL declare z_curs cursor for

      select * from customer_ansi

      for read only;

使用 FOR UPDATE 选项

使用 FOR UPDATE 选项可声明更新游标。您可以使用更新游标修改(更新或删除)当前的行。

在兼容 ANSI 的数据库中,如果一个 Select 游标不是使用 FOR READ ONLY 关键字声明的,并且该游标遵守在与游标相关联的 SELECT 语句的子集中描述的对更新游标的限制,那么可以使用该 Select 游标更新或删除数据。在声明游标时不需要使用 FOR UPDATE 关键字。

下面的示例声明一个更新游标:

EXEC SQL declare new_curs cursor for

      select * from customer_notansi

      for update;

在更新游标中,可以更新或是删除活动集中的行。在创建更新游标之后,可以通过使用带 WHERE CURRENT OF 子句的 UPDATE 或 DELETE 语句更新或删除当前选择的行。单词 CURRENT OF 是指最近取得的行;它们替代 WHERE 子句中通常的测试表达式。

更新游标能让您执行使用 UPDATE 语句不可能实现的更新操作,因为做出更新的决定以及新数据项的值取决于行的原始内容。您的程序可以在决定是否更新之前评估或操纵选择的数据。UPDATE 语句无法询问正在更新的表。

您可以指定那些可以被更新的特殊列。这些列不需要出现在 Projection 子句的 Select 列表中。

连同列的列表使用 FOR UPDATE

当声明更新游标时,您可以通过包含 OF 关键字和列的列表将更新操作限制在特定的列。您只可以修改随后 UPDATE 语句中的那些命名的列。列不需要在 SELECT 子句的选择列表中。

下一个示例声明了一个更新游标,并指定该游标只可以更新 customer_notansi 表中的 fname 和 lname 列:

EXEC SQL declare name_curs cursor for

        select * from customer_notansi

        for update of fname, lname;

缺省情况下,除非声明为 FOR READ ONLY ,否则在兼容 ANSI 的数据库中的 Select 游标是一个更新游标,因此 FOR UPDATE 关键字是可选的。但是,如果希望更新游标只能够修改表中的一些列,则必须在 FOR UPDATE OF column 列表中指定这些列。

指定列的主要好处是便于文档的编制并防止编程出错。(数据库服务器拒绝更新任何其它列。)另一个好处是在 SELECT 语句满足以下条件时性能得到增强:

  1. 可以使用索引处理 SELECT 语句。
  2. 列出的列不是用于处理 SELECT 语句的索引的一部分。

如果打算更新的列是用于处理 SELECT 语句的索引的一部分,则数据库服务器会保留一个列表,其中列有每个更新的行,从而确保没有任何行被更新两次。如果 OF 关键字指定了可以更新的列,则数据库服务器便会确定是否要保留更新行的列表。如果数据库服务器确定保留该列表的工作已不再需要,则性能随之提高。如果不使用 OF column 列表,数据库服务器通常会维护一个更新行的列表,尽管此列表可能并不需要。

下面的示例包含将更新游标同 DELETE 语句使用删除当前行的 GBase 8s ESQL/C 代码。

每当删除行时,游标仍处于行之间。在删除数据之后,必须在可以引用 DELETE 或 UPDATE 语句中的游标之前使用 FETCH 语句将游标推进到下一行。

EXEC SQL declare q_curs cursor for

   select * from customer where lname matches :last_name for update;

EXEC SQL open q_curs;

for (;;)

{

   EXEC SQL fetch q_curs into :cust_rec;

   if (strncmp(SQLSTATE, "00", 2) != 0)

      break;

   /* Display customer values and prompt for answer */

   printf("\n%s %s", cust_rec.fname, cust_rec.lname);

   printf("\nDelete this customer? ");

   scanf("%s", answer);

   if (answer[0] == 'y')

      EXEC SQL delete from customer where current of q_curs;

   if (strncmp(SQLSTATE, "00", 2) != 0)

      break;

}

printf("\n");

EXEC SQL close q_curs;

使用 Update 游标进行锁定

FOR UPDATE 关键字告知数据库服务器更新操作是可能的,并会引发数据库服务器使用比对 Select 游标更严格的锁定。您声明一个更新游标可让数据库服务器知道程序可能更新(或删除)它取得的作为 SELECT 语句一部分的任何行,更新游标为程序取得的行使用可升级锁定(也称写锁)。在程序修改行之前,会将行锁提升为互斥锁。

使用 WITH HOLD 关键字声明一个更新游标是可能的,但是这样做的唯一原因是将一长串的更新打断成较小的事务。您必须在同一个事务中取得并更新特定的行。

如果操作涉及取和更新大量的行,则数据库服务器维护的锁表会溢出。防止这种溢出的通常方式是锁定整个正在更新的表。如果此操作是不可能的,那么一种替换的方式是通过 Hold 游标来更新,并按时间间隔执行 COMMIT WORK 。但是,您必须谨慎地计划这样的应用程序,因为 COMMIT WORK 会释放所有的锁,甚至是那些通过 Hold 游标放置的锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值