VastbaseG100

基于openGauss内核开发的企业级关系型数据库。

Menu

逐行获取查询结果

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;
}