逐行获取查询结果
libpq设置逐行返回结果
libpq会收集一个SQL命令的整个结果并且把它作为单个PGresult返回给应用。这对于返回大量行的命令是行不通的。对于这类情况,应用可以使用PQsendQuery和PQgetResult的单行模式。在这种模式中,结果行以一次一行的方式被返回给应用。
要进入到单行模式,在一次成功的PQsendQuery(或者其他兄弟函数)调用后立即调用PQsetSingleRowMode。这种模式选择只对当前正在执行的查询有效。然后反复调用PQgetResult,直到它返回空。如果该查询返回一行数据,会将其作为单个的PGresult对象返回,其状态代码是PGRES_SINGLE_TUPLE而非PGRES_TUPLES_OK。在最后一行之后或者紧接着该查询返回零行之后,一个状态为PGRES_TUPLES_OK的零行对象会被返回,这就是代表不会有更多行的信号(但是注意仍然有必要继续调用PQgetResult直到它返回空)。所有这些PGresult对象将包含相同的行描述数据(列名、类型等等),这些数据和通常一个查询的PGresult对象的相同,使用后每一个对象都应该用PQclear释放。
示例
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"
static void
exit_nicely(PGconn *conn)
{
PQfinish(conn);
exit(1);
}
int main(int argc, char **argv)
{
const char *conninfo;
PGconn *conn;
PGresult *res;
int i,j;
/*
* 如果用户在命令行上提供了一个参数,将它用作连接信息串。
* 否则默认用设置 dbname=postgres 并且为所有其他链接参数使用环境变量或默认值。
*/
if (argc > 1)
conninfo = argv[1];
else
conninfo = "dbname = postgres";
/* 建立到数据库的一个连接 */
conn = PQconnectdb(conninfo);
/* 检查看后端连接是否成功建立 */
if (PQstatus(conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s",
PQerrorMessage(conn));
exit_nicely(conn);
}
const char *DML_statement="select * from pg_database;";
int status = PQsendQuery(conn,DML_statement);
int isSingleMode=PQsetSingleRowMode(conn);
res = PQgetResult(conn);
printf("print out 1 if it is single mode: %d\n", isSingleMode);
int isPrintName = 1;
int nFields;
while (res != 0)
{
/* 最后的空行 */
if (PQresultStatus(res)==PGRES_TUPLES_OK)
{
PQclear(res);
break;
}
/* 逐行返回结果 */
else if (PQresultStatus(res) == PGRES_SINGLE_TUPLE)
{
nFields = PQnfields(res); /* 获取属性数量 */
if(isPrintName) /* 打印属性名 */
{
for (i = 0; i < nFields; i++)
printf("%-15s", PQfname(res, i)); /* 获取属性名并打印 */
printf("\n\n");
isPrintName = 0;
}
for (j = 0; j < nFields; j++) /* 循环获取元组每个属性的值 */
printf("%-15s", PQgetvalue(res, 0, j));
printf("\n");
PQclear(res); /* 清理 */
res = PQgetResult(conn); /* 继续获取结果 */
}
else /* 未知错误 */
{
printf("Error Occured: %d\n", PQresultStatus(res));
PQclear(res);
break;
}
}
/* 关闭到数据库的连接并且清理 */
PQfinish(conn);
return 0;
}