更新时间:2026-07-28 GMT+08:00
处理结果集
- 返回单行结果的SELECT语句可以直接使用EXEC SQL执行,请参见执行SQL语句章节。
示例:
/* 首先建立一个表并插入数据 */ EXEC SQL CREATE TABLE test_table (number1 integer, number2 integer); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (2, 1); /* 查询结果为单行,:num 为宿主变量 */ EXEC SQL SELECT number1 INTO :num FROM test_table WHERE number2 = 1;
- 若要处理多行结果集,则必须使用游标,如何使用游标请参考使用游标。 示例:
/* 首先建立一个表并插入数据 */ EXEC SQL CREATE TABLE test_table (number1 integer, number2 integer); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (2, 1); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (3, 1); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (4, 1); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (5, 1); /* 定义宿主变量 */ EXEC SQL BEGIN DECLARE SECTION; int v1; int v2; EXEC SQL END DECLARE SECTION; /* 声明游标 */ EXEC SQL DECLARE test_bar CURSOR FOR SELECT number1, number2 FROM test_table ORDER BY number1; /* 打开游标 */ EXEC SQL OPEN test_bar; /* 当游标到达结果集末尾时跳出循环 */ EXEC SQL WHENEVER NOT FOUND DO BREAK; /* 获取查询结果集 */ while(1) { EXEC SQL FETCH NEXT FROM test_bar INTO :v1, :v2; printf("number1 = %d, number2 = %d\n",v1,v2); } /* 关闭游标 */ EXEC SQL CLOSE test_bar;
使用游标
使用游标可以检索出多行的结果集,应用程序必须声明一个游标并且从游标中抓取每一行数据。
- 声明一个游标:
EXEC SQL DECLARE c CURSOR FOR SELECT * FROM tb1;
- 打开游标:
EXEC SQL OPEN c;
- 从游标中抓取一行数据:
EXEC SQL FETCH 1 IN c INTO :a, :str;
- 关闭游标:
EXEC SQL CLOSE c;
在开启GUC参数enable_ecpg_cursor_duplicate_operation(默认开启)的情况下,使用ecpg连接ORA兼容数据库时,允许通过如下方式重复打开/关闭游标:
EXEC SQL OPEN c; EXEC SQL OPEN c; EXEC SQL CLOSE c; EXEC SQL CLOSE c;
更多游标的使用细节请参见DECLARE,关于FETCH命令的细节请参见《参考》中“SQL参考 > SQL语法 > F > FETCH”章节。
完整使用示例:
前提条件:需要提前创建testdb数据库。
#include <string.h>
#include <stdlib.h>
int main(void)
{
EXEC SQL BEGIN DECLARE SECTION;
int *a = NULL;
char *str = NULL;
EXEC SQL END DECLARE SECTION;
int count = 0;
/* 提前创建testdb */
EXEC SQL CONNECT TO testdb ;
EXEC SQL SET AUTOCOMMIT TO OFF;
EXEC SQL BEGIN;
EXEC SQL DROP TABLE IF EXISTS tb1;
EXEC SQL CREATE TABLE tb1(id int, info text);
EXEC SQL INSERT INTO tb1 (id, info) SELECT generate_series(1, 100000), 'test';
EXEC SQL SELECT COUNT(*) INTO :a FROM tb1;
printf ("a is %d\n", *a);
EXEC SQL COMMIT;
/* 定义游标 */
EXEC SQL DECLARE c CURSOR FOR SELECT * FROM tb1;
/* 打开游标 */
EXEC SQL OPEN c;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while(1) {
/* 抓取数据 */
EXEC SQL FETCH 1 IN c INTO :a, :str;
count++;
if (count == 100000) {
printf("Fetch res: a is %d, str is %s", *a, str);
}
}
/* 关闭游标 */
EXEC SQL CLOSE c;
EXEC SQL SET AUTOCOMMIT TO ON;
EXEC SQL DROP TABLE tb1;
EXEC SQL DISCONNECT;
ECPGfree_auto_mem();
return 0;
} 运行结果如下:
a is 100000 Fetch res: a is 100000, str is test
当cursor指向表的某一行时,可以使用WHERE CURRENT OF cursor_name语法更新或删除cursor当前指向的行。使用限制及约束请参见《参考》中“SQL参考 > SQL语法 > U > UPDATE”章节对此语法介绍。
完整使用示例:
#include <string.h>
#include <stdlib.h>
int main(void)
{
EXEC SQL BEGIN DECLARE SECTION;
int va;
int vb;
EXEC SQL END DECLARE SECTION;
int count = 0;
/* 提前创建testdb */
EXEC SQL CONNECT TO testdb;
EXEC SQL SET AUTOCOMMIT TO OFF;
EXEC SQL BEGIN;
EXEC SQL DROP TABLE IF EXISTS t1;
EXEC SQL CREATE TABLE t1(c1 INT, c2 INT);
EXEC SQL INSERT INTO t1 VALUES(generate_series(1, 10000), generate_series(1, 10000));
EXEC SQL COMMIT;
/* 定义游标 */
EXEC SQL DECLARE cur1 CURSOR FOR SELECT * FROM t1 WHERE c1 < 100 FOR UPDATE;
/* 打开游标 */
EXEC SQL OPEN cur1;
/* 抓取数据 */
EXEC SQL FETCH 1 IN cur1 INTO :va, :vb;
printf("c1: %d, c2: %d\n", va, vb);
/* 使用 WHERE CURRENT OF 删除当前行 */
EXEC SQL DELETE FROM t1 WHERE CURRENT OF cur1;
/* 继续抓取数据 */
EXEC SQL FETCH 1 IN cur1 INTO :va, :vb;
EXEC SQL FETCH 1 IN cur1 INTO :va, :vb;
printf("c1: %d, c2: %d\n", va, vb);
/* 使用 WHERE CURRENT OF 更新当前行 */
EXEC SQL UPDATE t1 SET c2 = 21 WHERE CURRENT OF cur1;
/* 查询更新后的数据 */
EXEC SQL SELECT c2 INTO :vb FROM t1 WHERE c1 = :va;
printf("c1: %d, c2: %d\n", va, vb);
/* 关闭游标 */
EXEC SQL CLOSE cur1;
/* 恢复自动提交并清理 */
EXEC SQL SET AUTOCOMMIT TO ON;
EXEC SQL DROP TABLE t1;
EXEC SQL DISCONNECT;
ECPGfree_auto_mem();
return 0;
} 运行结果如下:
c1: 1, c2: 1 c1: 3, c2: 3 c1: 3, c2: 21
父主题: 嵌入式SQL-C程序开发