我是使用libpq并在postgresql数据库上工作的新手。
所以,我可以使用C程序插入/更新/等一个postgresql数据库,只要我在引号内给出实际值。
我想知道如何在命令??
中传递字符串/整数变量E.g。以下代码将一个名为“comment”的列添加到现有表“people”中,其中包含“TRUE”默认值。我需要将“comment”的值更新为“FALSE”,其中id = 2。
#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'
请帮我提一些建议。
答案 0 :(得分:6)
有两种方法可以解决这个问题。第一种是准备字符串,并在其中插入值。第二种是使用可以单独替换值的查询参数。
对于第一种方法,您可以使用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 */
);
此功能允许您以文本或二进制格式提供参数和/或获得结果。为简单起见,我上面的示例假定两者都有文本格式。
对此的变体是使用预准备语句。在这种情况下,您对libpq进行两次单独调用:
根据上面的示例,调用PQprepare,您将SQL语句传递给参数值$ 1,$ 2等。这将返回一个语句句柄。
调用PQexecPrepared,您传递语句句柄以及参数本身,以与PQexecParams类似的方式指定。
使用这样的两个步骤的好处是,您可以准备一次,并执行多次,这样可以减少与解析和规划查询相关的服务器开销。