更新时间:2026-07-28 GMT+08:00
使用非初级类型的宿主变量
非初级类型的宿主变量包括数组、typedef、结构体和指针类型的宿主变量。
数组
有两种将数组作为宿主变量的情况。
- 在char[]或者VARCHAR[]中存储文本字符串。
- 在检索多行查询结果时不使用游标。
如果不使用数组,则处理多行查询结果时必须使用游标以及FETCH命令。但是如果使用数组类型作为宿主变量,则一次可以检索多行。数组长度需能容纳查询结果的所有行,否则可能会发生缓冲区溢出。
下面示例为扫描pg_database系统表并且显示所有可用数据库的OID和名称:
前提条件:需要创建testdb库。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
EXEC SQL BEGIN DECLARE SECTION;
int dbid[8];
char dbname[8][16];
int i;
EXEC SQL END DECLARE SECTION;
memset(dbname, 0, sizeof(char)* 16 * 8);
memset(dbid, 0, sizeof(int) * 8);
/* 连接到testdb */
EXEC SQL CONNECT TO testdb;
/* 一次检索多行到数组中。 */
EXEC SQL SELECT oid,datname INTO :dbid, :dbname FROM pg_database;
for (i = 0; i < 8; i++)
printf("oid=%d, dbname=%s\n", dbid[i], dbname[i]);
EXEC SQL COMMIT;
EXEC SQL DISCONNECT ALL;
return 0;
} 运行结果如下(具体值取决于本地环境):
oid=1, dbname=template1 oid=11510, dbname=template0 oid=11511, dbname=postgres oid=313780, dbname=testdb oid=0, dbname= oid=0, dbname= oid=0, dbname=
结构体
结构体成员变量可用来匹配查询结果列的名称,该结构能在一个宿主变量中处理多列值。
以下示例从pg_database系统表以及使用pg_database_size()函数检索可用数据库的OID、名称和尺寸。在此示例中,按照结构体的成员名匹配SELECT结果的每一列,而不必将多个宿主变量放在FETCH语句中。
EXEC SQL BEGIN DECLARE SECTION;
typedef struct
{
int oid;
char datname[65];
long long int size;
} dbinfo_t;
dbinfo_t dbval;
EXEC SQL END DECLARE SECTION;
memset(&dbval, 0, sizeof(dbinfo_t));
EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size FROM pg_database;
EXEC SQL OPEN cur1;
/* 在达到结果集末尾时,跳出 while 循环 */
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* 将多列取到一个结构体中。 */
EXEC SQL FETCH FROM cur1 INTO :dbval;
/* 打印该结构体的成员。 */
printf("oid=%d, datname=%s, size=%lld\n", dbval.oid, dbval.datname, dbval.size);
}
EXEC SQL CLOSE cur1; 运行结果如下(具体值取决于本地环境):
oid=1, datname=template1, size=4324580 oid=11510, datname=template0, size=4243460 oid=11511, datname=postgres, size=4324580 oid=313780, datname=testdb, size=8183012
结构体宿主变量可将查询结果的部分列转化成结构体字段,其他的查询结果列可以被分配给其它宿主变量。上述的示例也可以使用结构体外部的size宿主变量重新构造:
EXEC SQL BEGIN DECLARE SECTION;
typedef struct
{
int oid;
char datname[65];
} dbinfo_t;
dbinfo_t dbval;
long long int size;
EXEC SQL END DECLARE SECTION;
memset(&dbval, 0, sizeof(dbinfo_t));
EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size FROM pg_database;
EXEC SQL OPEN cur1;
/* 在达到结果集末尾时,跳出 while 循环 */
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* 将多列取到一个结构中。 */
EXEC SQL FETCH FROM cur1 INTO :dbval, :size;
/* 打印该结构的成员。 */
printf("oid=%d, datname=%s, size=%lld\n", dbval.oid, dbval.datname, size);
}
EXEC SQL CLOSE cur1; typedef
使用typedef关键字将新类型映射到已有类型:
EXEC SQL BEGIN DECLARE SECTION; typedef char mychartype[40]; typedef long serial_t; EXEC SQL END DECLARE SECTION;
也可以使用如下命令:
EXEC SQL TYPE serial_t IS long;
这种声明不需要写在一个声明段中。
指针
可以声明常见类型的指针:
EXEC SQL BEGIN DECLARE SECTION; int *intp; char **charp; EXEC SQL END DECLARE SECTION;
父主题: 数据类型和宿主变量