| 通过 SQL 程序修改数据 / DELETE 语句 | |
int delDupOrder()
{
int ord_num;
int dup_cnt, ret_code;
EXEC SQL declare scan_ord cursor for
select order_num, order_date
into :ord_num, :ord_date
from orders for update;
EXEC SQL open scan_ord;
if (sqlca.sqlcode != 0)
return (sqlca.sqlcode);
EXEC SQL begin work;
for(;;)
{
EXEC SQL fetch next scan_ord;
if (sqlca.sqlcode != 0) break;
dup_cnt = 0; /* default in case of error */
EXEC SQL select count(*) into dup_cnt from orders
where order_num = :ord_num;
if (dup_cnt > 1)
{
EXEC SQL delete from orders
where current of scan_ord;
if (sqlca.sqlcode != 0)
break;
}
}
ret_code = sqlca.sqlcode;
if (ret_code == 100) /* merely end of data */
EXEC SQL commit work;
else /* error on fetch or on delete */
EXEC SQL rollback work;
return (ret_code);
}
该函数的目的是删除包含重复的订单号码的行。实际上,在演示数据库中,orders.order_num 列有唯一约束,因此,其中不可出现重复的行。然而,可为另一数据库编写一个类似的函数;这一个使用熟悉的列名称。
该函数声明游标 scan_ord 来扫描 orders 表中的所有行。使用 FOR UPDATE 子句声明它,说明该游标可修改数据。如果该游标正确地打开,则该函数开始一个事务,然后对表的行进行循环。对于每一行,它使用嵌入式 SELECT 语句来确定该表的多少行具有当前行的订单编号。如果没有正确的隔离级别,此步骤失败,如 对多用户环境编程 描述的那样。)
在演示数据库中,使用它在此表上的唯一约束,返回到 dup_cnt 的计数始终为一。然而,如果它更大,则该函数删除表的当前行,将重复的计数减少一个。
有时需要这类清理函数,但它们一般需要更复杂的设计。此函数删除所有重复的行,除了数据库服务器返回的最后一行之外。那个顺序对这些行的内容及其含义没有任何关系。您或许可通过将 ORDER BY 子句添加到游标声明来提升前面例子中函数的性能。然而,您不可同时使用 ORDER BY 与 FOR UPDATE。插入示例 提供一种更好的方法。