Skip to content

SOCI

Databases & CachingDatabaseC++

What it is

SOCI is a C++ database access library that provides a clean, type-safe, and object-oriented abstraction over SQL databases. It acts like a lightweight ORM but retains full SQL control, offering both simplicity and flexibility.

SOCI allows developers to write queries in natural SQL while providing type-safe bindings to C++ variables. It eliminates manual binding and fetching of data, making database interaction safer and cleaner.

Installation

sudo apt install libsoci-dev

Getting started

The smallest useful thing you can do with it, and what each part means.

Connecting to a database
#include <soci/soci.h>
#include <iostream>

int main() {
    try {
        soci::session sql(soci::postgresql, "dbname=mydb user=myuser password=mypass");
        std::cout << "Connected successfully!" << std::endl;
    } catch (std::exception const &e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    return 0;
}
Opens a connection to a PostgreSQL database using SOCI.

Advanced usage

Where the library earns its place over a simpler alternative.

Executing queries
int count;
sql << "SELECT COUNT(*) FROM users", soci::into(count);
std::cout << "User count: " << count << std::endl;
Executes a query and stores the result directly into a C++ variable.
Fetching multiple rows
soci::rowset<soci::row> rs = (sql.prepare << "SELECT id, name FROM users");
for (auto const &r : rs) {
    int id = r.get<int>(0);
    std::string name = r.get<std::string>(1);
    std::cout << id << ": " << name << std::endl;
}
Iterates over query results using SOCI’s rowset abstraction.
Binding parameters
std::string name = "John";
int age;
sql << "SELECT age FROM users WHERE name = :name", soci::into(age), soci::use(name);
Binds C++ variables safely to SQL query parameters.
Transactions
{
    soci::transaction tr(sql);
    sql << "INSERT INTO logs(message) VALUES('test')";
    tr.commit();
}
Executes queries inside a transaction with explicit commit or rollback.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

soci_error: Cannot establish connection
Check database credentials, network connectivity, and that the backend driver is installed.
Row not found exception
Use `sql.get_single_result()` cautiously or check for empty results before accessing.
Type conversion error
Ensure correct C++ types are mapped to SQL columns (e.g., `int` to INTEGER, `std::string` to TEXT).

Best practices

  • Use parameter binding (`soci::use`) to avoid SQL injection.
  • Wrap multiple statements in transactions for safety and efficiency.
  • Catch exceptions from SOCI queries to handle runtime errors gracefully.
  • Use `rowset` for large result sets to stream data instead of loading all at once.
  • Leverage backend-specific options (e.g., PostgreSQL vs MySQL) for performance tuning.

Background

Why it exists, and what it was reacting to.

SOCI (The C++ Database Access Library) was started in 2004 by Maciej Sobczak to provide a modern alternative to traditional C database APIs like ODBC and libpq. It focuses on safety, readability, and minimal boilerplate while avoiding the complexity of full ORM frameworks. It supports multiple backends including PostgreSQL, MySQL, SQLite, Oracle, and ODBC.