使用游标删除 包含一个 DELETE 语句的示例,其目的在于查找并删除表的重复的行。执
行此任务的更好方式是选择期望的行,而不是删除不期望的行。下列 GBase 8s ESQL/C 示
例中的代码展示执行此任务的一种方法:
EXEC SQL BEGIN DECLARE SECTION;
long last_ord = 1;
struct {
long int o_num;
date o_date;
long c_num;
char o_shipinst[40];
char o_backlog;
char o_po[10];
date o_shipdate;
decimal o_shipwt;
decimal o_shipchg;
date o_paiddate;
} ord_row;
EXEC SQL END DECLARE SECTION;
EXEC SQL BEGIN WORK;
EXEC SQL INSERT INTO new_orders
SELECT * FROM orders main
WHERE 1 = (SELECT COUNT(*) FROM orders minor
WHERE main.order_num = minor.order_num);
EXEC SQL COMMIT WORK;
EXEC SQL DECLARE dup_row CURSOR FOR
SELECT * FROM orders main INTO :ord_row
WHERE 1 < (SELECT COUNT(*) FROM orders minor
WHERE main.order_num = minor.order_num)
ORDER BY order_date;
EXEC SQL DECLARE ins_row CURSOR FOR
INSERT INTO new_orders VALUES (:ord_row);
EXEC SQL BEGIN WORK;
GBase 8s SQL 指南:教程
南大通用数据技术股份有限公司 - 232 -
EXEC SQL OPEN ins_row;
EXEC SQL OPEN dup_row;
while(SQLCODE == 0)
{
EXEC SQL FETCH dup_row;
if(SQLCODE == 0)
{
if(ord_row.o_num != last_ord)
EXEC SQL PUT ins_row;
last_ord = ord_row.o_num
continue;
}
break;
}
if(SQLCODE != 0 && SQLCODE != 100)
EXEC SQL ROLLBACK WORK;
else
EXEC SQL COMMIT WORK;
EXEC SQL CLOSE ins_row;
EXEC SQL CLOSE dup_row;
此示例以一个常规的 INSERT 语句开始,该语句查找该表的所有非重复的行,并将它们插
入到另一表内,假定在程序启动之前已创建了该表。那个操作仅留下重复的行。(在演示
数据库中,orders 表有唯一约束,不可有重复的行。假设此示例处理的是其他数据库。)
然后,前面示例中的代码声明两个游标。第一个称为 dup_row,返回表中的重复的行。由
于 dup_row 仅用于输入,因此,它可使用 ORDER BY 子句来强制一些重复的顺序,而不
是在 使用游标删除 页上的示例中使用的物理记录顺序。在此示例中,按重复的行的日期对
它们排序,保留最早的日期,但您可基于该数据使用任何其他的顺序。
第二个游标 ins_row 是插入游标。此游标利用该能力来使用 C 结构 ord_row,以支持该行
中所有列的值。
剩余的代码检查通过 dup_row 返回的行。它将来自每一组重复的行中的第一行插入到新表
内,并忽略其余的。
为了简洁起见,前面的示例使用最简单的错误处理类型。如果在已处理了所有行之前发生
错误,则该样例代码回滚活动的事务。
多少行受到了影响?
当您的程序使用游标来选择行时,
它可测试 SQLCODE 是否为 100
(或 SQLSTATE 是否
为 02000),即“数据的结束”返回代码。设置此代码来指示没有行或没有更多的行满足
GBase 8s SQL 指南:教程
南大通用数据技术股份有限公司 - 233 -
该查询条件。对于不符合 ANSI 的数据库,仅跟在 SELECT 语句之后在 SQLCODE 或
SQLSTATE 中设置“数据的结束”返回代码;不跟在 DELETE、INSERT 或 UPDATE 语
句之后使用它。对于符合 ANSI 的数据库,对于不影响任何行的更新、删除和插入操作,
也将 SQLCODE 设置为 100。
找不到数据的查询是不成功的。然而,仍将碰巧未更新或插入行的 UPDATE 或 DELETE
语句视为成功。它更新了或删除了它的 WHERE 子句表明它应更新或产出的行集;然而,
该集合为空。
同样地,即使当插入了的行的来源是 SELECT 语句,且该 SELECT 未选择任何行,
INSERT 语句也不设置“数据的结束”返回代码。因为该 INSERT 语句插入了要求它插入
的行数(即,零行),因此,该语句成功。
要了解插入了、更新了或删除了多少行,程序可测试 SQLERRD 的第三个元素。行的计数
在那里,这与 SQLCODE 中的值(零还是负的)无关。