使用 libpq 访问 PostgreSQL 遍历大数据结果集

2023-07-14 17:14:56 浏览数 (1)

示例

PostgreSQL 提供了游标定义、查询的 SQL 语法。

我们可以在 C 代码中使用 SQL 层提供的 CURSOR 游标查询数据结果集:

代码语言:javascript复制
/*
 * testlibpq.c
 *
 *      测试 libpq(PostgreSQL 前端库) 的 C 版本。
 */
#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         nFields;
    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);
    }

    /*
     * 我们的测试案例这里涉及使用一个游标,对它我们必须用在一个事务块内。
     * 我们可以在一个单一的 "select * from pg_database" 的 PQexec() 中做整个事情,
     * 但是作为一个好的例子它太琐碎。
     */

    /* 开始一个事务块 */
    res = PQexec(conn, "BEGIN");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }

    /*
     * 任何时候不再需要 PGresult 时,应该 PQclear 它来避免内存泄露
     */
    PQclear(res);

    /*
     * 从 pg_database 取得行,它是数据库的系统目录
     */
    res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }
    PQclear(res);

    res = PQexec(conn, "FETCH ALL in myportal");
    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }

    /* 首先,打印出属性名 */
    nFields = PQnfields(res);
    for (i = 0; i < nFields; i  )
        printf("%-15s", PQfname(res, i));
    printf("nn");

    /* 接下来,打印出行 */
    for (i = 0; i < PQntuples(res); i  )
    {
        for (j = 0; j < nFields; j  )
            printf("%-15s", PQgetvalue(res, i, j));
        printf("n");
    }

    PQclear(res);

    /* 关闭入口,我们不需要考虑检查错误 */
    res = PQexec(conn, "CLOSE myportal");
    PQclear(res);

    /* 结束事务 */
    res = PQexec(conn, "END");
    PQclear(res);

    /* 关闭到数据库的连接并且清理 */
    PQfinish(conn);

    return 0;
}

测试成功,哦耶!

libpq 方法

下面是 libpq 支持的方法,更多详细,参看 libpq API 文档:

SN(序号)

方法描述

1

PQconnectdbParams 开启一个到数据库服务器的新连接。

2

PQconnectdb 开启一个到数据库服务器的新连接。

3

PQexec 提交一个命令给服务器并且等待结果。

4

PQclear 释放与一个PGresult相关的存储。每一个命令结果不再需要时应该用PQclear释放。

5

PQntuples 返回查询结果中的行(元组)数。

6

PQnfields 返回查询结果中每一行的列(域)数。

7

PQgetvalue 返回一个PGresult的一行的单一域值。行和列号从 0 开始。调用者不应该直接释放该结果。

8

PQclear 释放与一个PGresult相关的存储。

9

PQfinish 关闭与服务器的连接。

0 人点赞