前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 libpq 访问 PostgreSQL 遍历大数据结果集

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

原创
作者头像
postgres
修改2023-07-14 17:14:56
3930
修改2023-07-14 17:14:56
举报
文章被收录于专栏:PostgreSQL 技术PostgreSQL 技术

示例

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("\n\n");

    /* 接下来,打印出行 */
    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 关闭与服务器的连接。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 示例
  • libpq 方法
相关产品与服务
数据库专家服务
数据库专家服务(Database Expert Service,DBexpert)为您提供专业化的数据库服务。仅需提交您的具体问题和需求,即可获得腾讯云数据库专家的专业支持,助您解决各类专业化问题。腾讯云数据库专家服务团队均有10年以上的 DBA 经验,拥有亿级用户产品的数据库管理经验,以及丰富的服务经验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档