将C变量传递给SQL命令

我是使用libpq并在postgresql数据库上工作的新手。

所以,我可以使用C程序插入/更新/等一个postgresql数据库,只要我在引号内给出实际值。

我想知道如何在命令中传递字符串/整数变量??

例如,以下代码将一个名为“comment”的列添加到现有表“people”中,其中包含“TRUE”默认值。 我需要将“comment”的值更新为“FALSE”,其中id = 2。

#include  #include  #include  #include  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' 

请帮我一些建议。

有两种方法可以解决这个问题。 第一种是准备字符串,并在其中插入值。 第二种是使用可以单独替换值的查询参数。

对于第一种方法,您可以使用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 */ } 

此缓冲区将包含SQL查询,包括变量id的实际值。

注意需要检查snprintf的返回值以查看缓冲区是否溢出。

另请注意,在命令中放置字符串时,需要确保该字符串不包含任何引号或其他特殊字符。 如果字符串来自您的程序之外,例如。 从用户输入,然后未能正确引用它留下了一个很大的漏洞,有人可能会注入一些恶意SQL。 libpq为此提供了PQescapeLiteral函数。

在大多数情况下,另一种方法是将SQL命令和参数分别传递给服务器。 例如,您可以使用PQexecParams libpq functoin执行此操作。 您的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 */ ); 

此function允许您以文本或二进制格式提供参数和/或获得结果。 为简单起见,我上面的示例假定两者的文本格式。

对此的一种变化是使用预准备语句。 在这种情况下,您对libpq进行两次单独调用:

  1. 根据上面的示例,调用PQprepare,您将SQL语句传递给参数值$ 1,$ 2等。 这将返回一个语句句柄。

  2. 调用PQexecPrepared,传递语句句柄以及参数本身,以与PQexecParams类似的方式指定。

使用这样的两个步骤的好处是,您可以准备一次语句并执行多次,这样可以减少与解析和规划查询相关的服务器开销。