1. 程式人生 > >postgresql從入門到菜鳥(六)libpq連線postgres資料庫

postgresql從入門到菜鳥(六)libpq連線postgres資料庫

上一期講了一些如何通過jdbc連線postgresql資料庫,這一期準備說一說如何通過libpq連線postgresql資料庫。
上一期的jdbc是postgresql的java語言應用程式介面,這一期的libpq對應的是postgresql的C語言應用程式介面。

這裡依舊分為三個模組來講:
一.獲取連線
二.執行select語句
三.執行insert,delete,update語句

第一部分:獲取連線
要使用libpq連線postgresql資料庫首先要引用libpq的標頭檔案libpq-fe.h

然後建立連線字串和PGconn結構體,設定連線字串後就可以通過連線字串獲取連線了

const char *conninfo;
PGconn     *conn;
conninfo = "host=127.0.0.1 port=5433 dbname=smoondb user=postgres";
conn = PQconnectdb(conninfo);

注意如果這裡預設連線關鍵字的話,libpq將使用預設關鍵字的預設值進行連線,連線關鍵字的預設值可以參考官方手冊。

在jdbc中,我們可以通過try catch的方式進行連線錯誤捕獲,在libpq中也提供了判斷連線是否成功建立的介面:

 if (PQstatus(conn) != CONNECTION_OK)
 {
        fprintf(stderr, "Connection to database failed: %s",
                PQerrorMessage(conn));
        exit_nicely(conn);//關閉連線並執行清理操作
 }

這裡如果連線不成功的話會返回服務端返回的錯誤message,如果成功的話後面就可以通過conn操作資料庫了。

第二部分:執行select語句
在獲取到PGconn例項後,我們就可利用PGconn例項進行對資料庫的操作了,和jdbc不同,jdbc中查詢語句和更新語句會分別呼叫executeQuery()和executeUpdate(),而libpq中使用的是同一個介面。

Lipq執行sql命令的核心函式為PQexec(PGconn *conn, const char *command);其中第一個引數為連線。第二個為執行的命令,其中command字串可以包含多條執行命令,需要注意的是如果不加入begin或者commit的關鍵字,command字串中的所有命令將在一個事務中執行,並且只要其中一條失敗,就會導致整個command執行失敗。

PQexec函式的返回型別為PGresult,如果返回值為null,說明執行失敗,可以通過PQerrorMessage()方法檢視錯誤訊息。

在libpg中,查詢語句和更新語句都是通過PQexec函式執行,但是很明顯對於這兩種語句我們需要的返回值肯定不同,所以在解析PGresult時,libpq提供了不同的解析函式,這部分先說說解析查詢結果用到的幾個函式

PQnfields(PGresult *res):用於獲取結果集中列的數目
PQfname(PGresult *res,int i):用於獲取結果集中列的名稱
PQntuples(PGresult *res):用於獲取結果集中行的數目
PQgetvalue(PGresult *res,int i,int j):用於獲取結果集中i行j列的值

比如下面這一段:

	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);
    }
    //這裡需要注意不再使用的PGresult需要及時釋放,否則可能會造成記憶體洩漏
    PQclear(res);

    res = PQexec(conn, "FETCH ALL in myportal");//FETCH ALL表示從結果中取回全部資料
    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);

第三部分:執行insert,delete,update語句
對於select語句,我們在解析PGresult時需要的是結果集,所以在上面呼叫了以上幾個函式,但是修改語句我們更關心的受影響的行數,所以對於修改語句可以通過PQntuples(const PGresult *res)獲取受影響函式,其中對於PGresult而言它的成員中包含了所有執行的結果,不同的解析函式只是用來取得PGresult中相應的成員而已,有興趣的同學可以去看一看PGresult結構體的實現,裡面對於所有的成員都有比較清楚的描述。
下面貼一段執行插入語句的例子:

    res = PQexec(conn, "delete from student where sid=4;");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "delete failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }
    printf("updatelin:%s",PQcmdTuples(res));//解析並列印受影響行數
    PQclear(res);

完整的例子程式可以在官方手冊中找到這裡就不再貼出了。

最後說說libpq程式的編譯,對於寫好的.c檔案,可以執行以下命令生成可執行檔案

gcc -L $libpath -I $includepath -lpq -o testlipq testlipq.c