通过 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。插入示例 提供一种更好的方法。