C++ и PostgreSQL: полное руководство для разработчика

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

C++ и PostgreSQL: как подружить системное программирование и реляционные базы данных

Вы когда-нибудь задумывались, почему многие высоконагруженные системы — от игровых серверов до финансовых платформ — выбирают связку C++ и PostgreSQL? Ответ прост: C++ даёт молниеносную скорость и контроль над памятью, а PostgreSQL — надёжность и мощные SQL-возможности. Это не просто «ещё один туториал». Это практическое руководство, которое проведёт вас от установки драйвера до написания полноценного CRUD-приложения на C++ с PostgreSQL.

В этой статье вы узнаете:

  • Как установить и настроить libpq — официальный клиент PostgreSQL для C++.
  • Как выполнять SELECT, INSERT, UPDATE и DELETE запросы.
  • Как обрабатывать ошибки и работать с транзакциями.
  • Примеры реального кода, который можно сразу использовать в своих проектах.

Готовы? Поехали!

Шаг 1. Установка libpq и подготовка окружения

Прежде чем писать код, нужно установить библиотеку libpq. Она входит в состав клиентской части PostgreSQL. Если у вас уже установлен PostgreSQL, libpq уже есть. Если нет — установите её отдельно.

Linux (Ubuntu/Debian)

sudo apt update
sudo apt install libpq-dev postgresql-server-dev-all

macOS (Homebrew)

brew install postgresql

Windows

Скачайте установщик с официального сайта PostgreSQL и при установке выберите компонент «Development Libraries».

После установки проверьте, что компилятор g++ может найти библиотеку. Для этого при компиляции нужно будет указать флаги -lpq (линковка с libpq) и, возможно, -I/путь/к/include.

Шаг 2. Подключение к базе данных на C++

Начнём с самого главного — установления соединения. Для этого используется структура PGconn и функция PQconnectdb().

Пример: простое подключение

#include <iostream>
#include <libpq-fe.h>

int main() {
    // Параметры подключения
    const char* conninfo = "host=localhost port=5432 dbname=mydb user=myuser password=mypass";

    // Устанавливаем соединение
    PGconn* conn = PQconnectdb(conninfo);

    // Проверяем статус
    if (PQstatus(conn) != CONNECTION_OK) {
        std::cerr << "Ошибка подключения: " << PQerrorMessage(conn) << std::endl;
        PQfinish(conn);
        return 1;
    }

    std::cout << "Подключение к PostgreSQL успешно!" << std::endl;

    // Закрываем соединение
    PQfinish(conn);
    return 0;
}

Важно: никогда не хардкодьте пароли в коде. Используйте переменные окружения или файлы конфигурации. В примере выше показано для наглядности.

Скомпилируем:

g++ -o connect connect.cpp -lpq

Шаг 3. Выполнение SQL-запросов: SELECT, INSERT, UPDATE, DELETE

Теперь, когда соединение установлено, научимся выполнять запросы. Для этого используется функция PQexec(), которая возвращает результат в виде структуры PGresult.

Пример: выполнение SELECT

PGresult* res = PQexec(conn, "SELECT id, name, age FROM users");

if (PQresultStatus(res) != PGRES_TUPLES_OK) {
    std::cerr << "Ошибка запроса: " << PQerrorMessage(conn) << std::endl;
    PQclear(res);
    PQfinish(conn);
    return 1;
}

// Получаем количество строк и столбцов
int rows = PQntuples(res);
int cols = PQnfields(res);

// Выводим заголовки столбцов
for (int i = 0; i < cols; ++i) {
    std::cout << PQfname(res, i) << "\t";
}
std::cout << std::endl;

// Выводим данные
for (int i = 0; i < rows; ++i) {
    for (int j = 0; j < cols; ++j) {
        std::cout << PQgetvalue(res, i, j) << "\t";
    }
    std::cout << std::endl;
}

PQclear(res);

Пример: INSERT с параметрами (безопасно)

Никогда не конкатенируйте строки для SQL! Используйте параметризованные запросы через PQexecParams().

const char* paramValues[2] = {"Alice", "30"};
int paramLengths[2] = {5, 2}; // длины строк
int paramFormats[2] = {0, 0}; // текстовый формат

PGresult* res = PQexecParams(conn,
    "INSERT INTO users (name, age) VALUES ($1, $2)",
    2,          // количество параметров
    nullptr,    // типы параметров (NULL = автоопределение)
    paramValues,
    paramLengths,
    paramFormats,
    0);         // текстовый формат результата

if (PQresultStatus(res) != PGRES_COMMAND_OK) {
    std::cerr << "Ошибка INSERT: " << PQerrorMessage(conn) << std::endl;
} else {
    std::cout << "Запись добавлена!" << std::endl;
}

PQclear(res);

Почему это важно? Параметризованные запросы защищают от SQL-инъекций. Даже если пользователь введёт '; DROP TABLE users; --, база данных воспримет это как строку, а не как команду.

Шаг 4. Обработка ошибок и работа с транзакциями

Ошибки в работе с БД неизбежны. Всегда проверяйте статус результата после каждого запроса. Для транзакций используйте команды BEGIN, COMMIT и ROLLBACK через PQexec().

Пример транзакции

// Начинаем транзакцию
PQexec(conn, "BEGIN");

// Первый запрос
PGresult* res1 = PQexec(conn, "UPDATE accounts SET balance = balance - 100 WHERE id = 1");
if (PQresultStatus(res1) != PGRES_COMMAND_OK) {
    PQexec(conn, "ROLLBACK");
    std::cerr << "Ошибка: " << PQerrorMessage(conn) << std::endl;
    PQclear(res1);
    return 1;
}
PQclear(res1);

// Второй запрос
PGresult* res2 = PQexec(conn, "UPDATE accounts SET balance = balance + 100 WHERE id = 2");
if (PQresultStatus(res2) != PGRES_COMMAND_OK) {
    PQexec(conn, "ROLLBACK");
    std::cerr << "Ошибка: " << PQerrorMessage(conn) << std::endl;
    PQclear(res2);
    return 1;
}
PQclear(res2);

// Если всё ок — фиксиру                

Блоги

Рекомендаций по книгам