PostgreSQL - C/C++ 接口:初学者指南

你好,未来的数据库巫师们!我很高兴能成为你们在这激动人心的PostgreSQL和C/C++世界之旅的向导。作为一名教授计算机科学多年的老师,我可以向您保证,这种组合就像花生酱和果酱一样——它们搭配得非常好!所以,让我们卷起袖子,一头扎进去。

PostgreSQL - C/C++

安装

在我们开始编码之前,我们需要设置我们的环境。想象一下,在烹饪美食之前准备厨房。我们需要两个主要成分:

  1. PostgreSQL
  2. libpq(PostgreSQL的C客户端库)

对于Windows用户,从官方网站下载PostgreSQL安装程序。安装就像安装其他程序一样简单——只需按照向导操作!

对于Linux的朋友们,甚至更简单。打开终端并输入:

sudo apt-get install postgresql postgresql-contrib libpq-dev

Mac用户,你们也不会被落下!使用Homebrew:

brew install postgresql

安装完成后,别忘了启动PostgreSQL服务。在大多数系统上,你可以这样做:

sudo service postgresql start

太好了!现在我们的厨房(我的意思是,开发环境)已经准备好了。让我们开始烹饪……我是说,编码!

C/C++ 接口API

PostgreSQL提供了一套C函数,允许我们与数据库交互。这些函数就像厨房中的铲子和搅拌器。以下是我们将要使用的主要函数:

函数 描述
PQconnectdb() 连接到数据库
PQfinish() 关闭数据库连接
PQexec() 执行SQL命令
PQstatus() 检查连接状态
PQresultStatus() 检查查询结果
PQntuples() 返回结果中的行数
PQnfields() 返回结果中的列数
PQgetvalue() 从结果中检索字段值

别担心,现在它们看起来可能令人生畏。我们很快就会使用每一个函数,您会发现它们实际上是多么友好!

连接到数据库

让我们从基础开始——连接到我们的数据库。这就好比敲门并说:“你好,PostgreSQL!我可以进来吗?”

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

int main() {
PGconn *conn = PQconnectdb("dbname=testdb user=john password=secret");

if (PQstatus(conn) == CONNECTION_BAD) {
fprintf(stderr, "连接到数据库失败: %s\n", PQerrorMessage(conn));
PQfinish(conn);
exit(1);
}

printf("成功连接到数据库!\n");
PQfinish(conn);
return 0;
}

让我们分解一下:

  1. 我们包含了必要的头文件,包括libpq-fe.h,它为我们提供了访问PostgreSQL函数的能力。
  2. 我们使用PQconnectdb()连接到我们的数据库。将“testdb”、“john”和“secret”替换为实际的数据库名称、用户名和密码。
  3. 我们使用PQstatus()检查连接是否成功。
  4. 如果成功,我们打印一条愉快的消息。如果不成功,我们打印错误并退出。
  5. 最后,我们使用PQfinish()关闭连接。

编译这个程序:

gcc -o connect connect.c -I/usr/include/postgresql -lpq

运行它,如果一切顺利,你会看到“成功连接到数据库!”。恭喜你,你已经和PostgreSQL握手了!

创建表

现在我们已经进来了,让我们创建一个表。这就好比在Excel中设置一个新的电子表格。

PGresult *res = PQexec(conn, "CREATE TABLE students (id SERIAL PRIMARY KEY, name VARCHAR(100), age INT)");

if (PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "创建表失败: %s\n", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(1);
}

printf("表成功创建!\n");
PQclear(res);

在这里,我们使用PQexec()执行一个SQL命令。我们正在创建一个名为“students”的表,包含三个列:id、name和age。id的SERIAL类型意味着它将自动为每个新条目递增——非常方便!

INSERT 操作

让我们向我们的表中添加一些数据。这就好比填写电子表格的行。

const char *insert_query = "INSERT INTO students (name, age) VALUES ($1, $2)";
const char *param_values[2] = {"Alice", "20"};
int param_lengths[2] = {strlen(param_values[0]), strlen(param_values[1])};
int param_formats[2] = {0, 0};

PGresult *res = PQexecParams(conn, insert_query, 2, NULL, param_values, param_lengths, param_formats, 0);

if (PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "INSERT失败: %s\n", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(1);
}

printf("数据成功插入!\n");
PQclear(res);

在这里,我们使用PQexecParams()而不是PQexec()。这个函数允许我们在查询中使用参数,这更安全、更高效。查询中的$1$2是参数的占位符。

SELECT 操作

现在,让我们检索我们的数据。这就好比查看我们在电子表格中写了什么。

PGresult *res = PQexec(conn, "SELECT * FROM students");

if (PQresultStatus(res) != PGRES_TUPLES_OK) {
fprintf(stderr, "SELECT失败: %s\n", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(1);
}

int rows = PQntuples(res);
int cols = PQnfields(res);

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%s\t", PQgetvalue(res, i, j));
}
printf("\n");
}

PQclear(res);

在这里,我们使用PQntuples()获取行数,PQnfields()获取列数,PQgetvalue()检索每个值。这就好比逐个单元格地查看我们的电子表格!

UPDATE 操作

有时我们需要更改数据。让我们更新Alice的年龄:

const char *update_query = "UPDATE students SET age = $1 WHERE name = $2";
const char *param_values[2] = {"21", "Alice"};
int param_lengths[2] = {strlen(param_values[0]), strlen(param_values[1])};
int param_formats[2] = {0, 0};

PGresult *res = PQexecParams(conn, update_query, 2, NULL, param_values, param_lengths, param_formats, 0);

if (PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "UPDATE失败: %s\n", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(1);
}

printf("数据成功更新!\n");
PQclear(res);

这和我们的INSERT操作相似,但我们使用的是UPDATE SQL命令。

DELETE 操作

最后,让我们学习如何删除数据。这就好比从我们的电子表格中擦除一行。

const char *delete_query = "DELETE FROM students WHERE name = $1";
const char *param_values[1] = {"Alice"};
int param_lengths[1] = {strlen(param_values[0])};
int param_formats[1] = {0};

PGresult *res = PQexecParams(conn, delete_query, 1, NULL, param_values, param_lengths, param_formats, 0);

if (PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "DELETE失败: %s\n", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(1);
}

printf("数据成功删除!\n");
PQclear(res);

就这样!我们已经涵盖了PostgreSQL和C的基本CRUD(创建、读取、更新、删除)操作。记住,熟能生巧。尝试组合这些操作,增加错误处理,很快你将成为PostgreSQL的忍者!

永远记得在完成后使用PQclear()释放你的结果,并用PQfinish()关闭你的连接。这就像烹饪后清理一样——它让你的厨房(和你的程序)运行顺畅。

未来的数据库大师们,祝你们编码愉快!愿你们的查询快速,连接永不中断!

Credits: Image by storyset