更新时间:2024-11-12 GMT+08:00
分享

数据库建连、执行SQL并返回结果

gcc编译libpq源程序,需要通过-I directory选项,提供头文件的安装位置(有些时候编译器会查找缺省的目录,因此可以忽略这些选项)。如:
gcc -I (头文件所在目录) -L (libpq库所在目录)  -o testlibpq testlibpq.c -lpq

执行命令为:

./testlibpq.c
如果要使用制作文件(makefile),向CPPFLAGS、LDFLAGS、LIBS变量中增加如下选项:
CPPFLAGS += -I (头文件所在目录)
LDFLAGS += -L (libpq库所在目录)
LIBS += -lpq
例如:
CPPFLAGS += -I$(GAUSSHOME)/include/libpq
LDFLAGS += -L$(GAUSSHOME)/lib
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
 * testlibpq.c
 * 说明: testlibpq.c源程序,提供libpq基本且常见的使用场景。
 * 使用libpq提供的PQconnectdb、PQexec、PQntuples、PQfinish等接口实现数据库建连,执行sql,获取返回结果以及资源清理。
 */
#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
#include <string.h>

static void
exit_nicely(PGconn *conn)
{
    PQfinish(conn);
    exit(1);
}

int main(int argc, char **argv)
{
    /* 此处user、passwd等变量应从环境变量或配置文件读取,环境变量需用户自己按需配置;非环境变量情况下可直接赋值字符串 */
    const char conninfo[1024];
    PGconn     *conn;
    PGresult   *res;
    int         nFields;
    int         i,j;
    char        *passwd = getenv("EXAMPLE_PASSWD_ENV");
    char        *port = getenv("EXAMPLE_PORT_ENV");
    char        *host = getenv("EXAMPLE_HOST_ENV");
    char        *username = getenv("EXAMPLE_USERNAME_ENV");
    char        *dbname = getenv("EXAMPLE_DBNAME_ENV");

    /*
     * 用户在命令行上提供了conninfo字符串的值时使用该值
     * 否则环境变量或者所有其它连接参数
     * 都使用缺省值。
     */
    if (argc > 1)
        strcpy(conninfo, argv[1]);
    else
        sprintf(conninfo,
            "dbname=%s port=%s host=%s application_name=test connect_timeout=5 sslmode=allow user=%s password=%s",
            dbname, port, host, username, passwd);

    /* 连接数据库 */
    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);
    }

    /*
     * 在结果不需要的时候PQclear PGresult,以避免内存泄漏
     */
    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;
}

示例运行结果如下,其中“user_name”表示数据库管理员用户名,根据具体使用环境会发生变化:

datname        datdba         encoding       datcollate     datctype       datistemplate  datallowconn   datconnlimit   datlastsysoid  datfrozenxid   dattablespace  datcompatibilitydatacl         datfrozenxid64 datminmxid     dattimezone    dattype

template_pdb   10             7              en_US.UTF-8    en_US.UTF-8    t              t              -1             12837          0              1663           A                             3              2              PRC            P
templatea      10             7              en_US.UTF-8    en_US.UTF-8    t              f              -1             12837          0              1663           A              {=c/user_name,user_name=CTc/user_name}41372          2              PRC            D
template1      10             7              en_US.UTF-8    en_US.UTF-8    t              t              -1             12837          0              1663           A              {=c/user_name,user_name=CTc/user_name}40414          2              PRC            D
templatem      10             7              en_US.UTF-8    en_US.UTF-8    t              t              -1             12837          0              1663           M              {=c/user_name,user_name=CTc/user_name}55146          2              PRC            D
template0      10             7              en_US.UTF-8    en_US.UTF-8    t              f              -1             12837          0              1663           A              {=c/user_name,user_name=CTc/user_name}39935          2              PRC            D
postgres       10             7              en_US.UTF-8    en_US.UTF-8    f              t              -1             12837          0              1663           A                             40893          2              PRC            D

相关文档