2

私は libpq を使用する初心者で、postgresql データベースで作業しています。

したがって、引用符内に実際の値を指定すれば、C プログラムを使用して postgresql データベースを挿入/更新/etc できます。

コマンドで文字列/整数変数を渡す方法を知りたいですか??

例: 次のコードは、"TRUE" のデフォルト値を含む "comment" という列を既存のテーブル "people" に追加します。ID = 2 の場合、「コメント」の値を「FALSE」で更新する必要があります。

    #include <stdio.h>
    #include <stdlib.h>
    #include <libpq-fe.h>
    #include <string.h>

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

 int main()
 {
     PGconn *conn;
     PGresult *res;
 int nFields;
 int row_count=0,col_count=0;
 int row=0;
 int col=0;

 conn = PQconnectdb("dbname=test host=localhost user=postgres password=xxx");

     if(PQstatus(conn) == CONNECTION_BAD) 
     {
    fprintf(stderr, "Connection to database \"%s\" failed.\n", PQerrorMessage(conn));
            fprintf(stderr, "%s", PQerrorMessage(conn));
            exit_nicely(conn);
     }

res = PQexec(conn, "ALTER TABLE people ADD comment VARCHAR(50) DEFAULT 'TRUE'");
if((!res) || PQresultStatus(res) != PGRES_COMMAND_OK) 
{
    fprintf(stderr, "Adding col to table (ALTER) Failed: %s", PQerrorMessage(conn));
    PQclear(res);
    exit_nicely(conn);
    }

res = PQexec(conn, "SELECT * FROM people");
if((!res) || (PQresultStatus(res) != PGRES_TUPLES_OK))
    {
        fprintf(stderr, "SELECT command did not return tuples properly\n");
        PQclear(res);
    }

int query1 = 2;
res = PQexec(conn,"UPDATE people SET comment='FALSE' WHERE id =\'query1\'");
if((!res) || PQresultStatus(res) != PGRES_COMMAND_OK) 
{
    fprintf(stderr, "Insertion Failed: %s", PQerrorMessage(conn));
    PQclear(res);
    exit_nicely(conn);
}
else
    printf("Successfully inserted value in Table..... \n");

res = PQexec(conn, "SELECT * FROM people");
if((!res) || (PQresultStatus(res) != PGRES_TUPLES_OK))
    {
         fprintf(stderr, "SELECT command did not return tuples properly\n");
         PQclear(res);
    }

    puts("==========================");

for(row=0;row<PQntuples(res);row++) 
{
        for(col=0;col<PQnfields(res);col++) 
        {
            printf("%s\t", PQgetvalue(res, row, col));
        }
        puts("");
    }

PQclear(res);

    PQfinish(conn);

    return 0;
  }

次の出力が必要です。

id | firstname | lastname | comment
1 | Fred | Flintstone | 5055551234 | TRUE
2 | Wilma | Flintstone | 5055551234 | FALSE
5 | XXX | YYY | 7633839276 | TRUE
3 | Barny | Rubble | 5055550000 | TRUE

ただし、次のエラーが発生します。

Insertion Failed: ERROR:  invalid input syntax for integer: "query1"
LINE 1: UPDATE people SET comment='FALSE' WHERE id ='query1'

いくつかの提案を手伝ってください。

4

1 に答える 1

6

これを処理するには 2 つの方法があります。1 つ目は、値が挿入された文字列を準備することです。2 つ目は、個別に値を代入できるクエリ パラメータを使用することです。

最初の方法では、 snprintfなどの関数を使用して、サーバーに送信するコマンドを準備できます。例えば:

char buffer[512];

int num=snprintf(buffer, sizeof(buffer), 
    "SELECT name FROM MYTABLE WHERE id=%d", id);

if (num>sizeof(buffer)) {
    /* error: buffer was too small */
}

このバッファの後、変数 id の実際の値を含む SQL クエリが含まれます。

バッファがオーバーフローしたかどうかを確認するには、snprintf からの戻り値をチェックする必要があることに注意してください。

また、文字列がコマンドに配置されている場合、文字列に引用符やその他の特殊文字が含まれていないことを確認する必要があることに注意してください。文字列がプログラムの外部からのものである場合。ユーザー入力から、それを適切に引用しないと、誰かが悪意のある SQL を挿入できる大きな穴が残ります。libpq は、このためのPQescapeLiteral関数を提供します。

ほとんどの場合に推奨されるもう 1 つの方法は、SQL コマンドとパラメーターをサーバーに別々に渡すことです。たとえば、PQexecParams libpq 関数を使用してこれを行うことができます。SQL 文字列は次のようになります。

PGresult r = PQexecParams(conn, /* Connection to database */
    "SELECT name FROM mytable WHERE id=$1",
    1,             /* Number of parameters */
    NULL,          /* NULL means server should figure out the parameter types */
    params,        /* Pointer to array of strings containing parameters */
    NULL,          /* Not needed unless binary format used */
    NULL,          /* Not needed unless binary format used */
    0              /* Result to come back in text format */
);

この関数を使用すると、パラメータを指定したり、結果をテキスト形式またはバイナリ形式で取得したりできます。簡単にするために、上記の例では両方のテキスト形式を想定しています。

これのバリエーションは、準備済みステートメントを使用することです。この場合、libpq に対して 2 つの別々の呼び出しを行います。

  1. 上記の例のように、パラメーター値 $1、$2 などで SQL ステートメントを渡す PQprepare を呼び出します。これにより、ステートメント ハンドルが返されます。

  2. PQexecParams と同様の方法で指定された、ステートメント ハンドルとパラメーター自体を渡す PQexecPrepared を呼び出します。

このような 2 つのステップを使用する利点は、ステートメントを 1 回準備して何度も実行できることです。これにより、ステートメントの解析とクエリの計画に関連するサーバーのオーバーヘッドが削減されます。

于 2014-04-14T23:54:05.153 に答える