Соединение связанных таблиц в C++
Когда данные разнесены по таблицам, для отчета нужны поля с обеих сторон.
Только совпавшие пары оставляет INNER JOIN,
где ключ ссылки совпал. Выборка отделов и
сотрудников с равенством идентификаторов
выглядит так:
#include <iostream>
#include <sqlite3.h>
int main() {
sqlite3* db = nullptr;
if (sqlite3_open("join_staff.db", &db) != SQLITE_OK) {
std::cerr << sqlite3_errmsg(db) << "\n";
sqlite3_close(db);
return 1;
}
sqlite3_exec(
db, "PRAGMA foreign_keys = ON",
nullptr, nullptr, nullptr
);
sqlite3_exec(
db,
"CREATE TABLE IF NOT EXISTS departments ("
"id INTEGER PRIMARY KEY, title TEXT NOT NULL)",
nullptr, nullptr, nullptr
);
sqlite3_exec(
db,
"CREATE TABLE IF NOT EXISTS staff ("
"id INTEGER PRIMARY KEY, dept_id INTEGER NOT NULL, "
"full_name TEXT NOT NULL, "
"FOREIGN KEY (dept_id) REFERENCES departments (id))",
nullptr, nullptr, nullptr
);
sqlite3_stmt* dept = nullptr;
sqlite3_prepare_v2(
db, "INSERT INTO departments (title) VALUES (?)",
-1, &dept, nullptr
);
sqlite3_bind_text(dept, 1, "Support", -1, SQLITE_STATIC);
sqlite3_step(dept);
sqlite3_finalize(dept);
sqlite3_stmt* member = nullptr;
sqlite3_prepare_v2(
db,
"INSERT INTO staff (dept_id, full_name) VALUES (?, ?)",
-1, &member, nullptr
);
sqlite3_bind_int(member, 1, 1);
sqlite3_bind_text(member, 2, "Alice Gray", -1, SQLITE_STATIC);
sqlite3_step(member);
sqlite3_reset(member);
sqlite3_bind_int(member, 1, 1);
sqlite3_bind_text(member, 2, "Ben Holt", -1, SQLITE_STATIC);
sqlite3_step(member);
sqlite3_finalize(member);
sqlite3_stmt* sel = nullptr;
sqlite3_prepare_v2(
db,
"SELECT s.full_name, d.title FROM staff s "
"INNER JOIN departments d ON s.dept_id = d.id "
"ORDER BY s.id",
-1, &sel, nullptr
);
while (sqlite3_step(sel) == SQLITE_ROW) {
const char* name = reinterpret_cast<const char*>(
sqlite3_column_text(sel, 0)
);
const char* title = reinterpret_cast<const char*>(
sqlite3_column_text(sel, 1)
);
std::cout << name << "\n";
std::cout << title << "\n";
}
sqlite3_finalize(sel);
sqlite3_close(db);
return 0;
}
Псевдонимы s и d сокращают имена
столбцов. Фильтр по отделу задают в WHERE
после соединения:
#include <iostream>
#include <sqlite3.h>
int main() {
sqlite3* db = nullptr;
if (sqlite3_open("join_filter.db", &db) != SQLITE_OK) {
std::cerr << sqlite3_errmsg(db) << "\n";
sqlite3_close(db);
return 1;
}
sqlite3_exec(
db, "PRAGMA foreign_keys = ON",
nullptr, nullptr, nullptr
);
sqlite3_exec(
db,
"CREATE TABLE IF NOT EXISTS departments ("
"id INTEGER PRIMARY KEY, title TEXT NOT NULL)",
nullptr, nullptr, nullptr
);
sqlite3_exec(
db,
"CREATE TABLE IF NOT EXISTS staff ("
"id INTEGER PRIMARY KEY, dept_id INTEGER NOT NULL, "
"full_name TEXT NOT NULL, "
"FOREIGN KEY (dept_id) REFERENCES departments (id))",
nullptr, nullptr, nullptr
);
sqlite3_stmt* dept = nullptr;
sqlite3_prepare_v2(
db, "INSERT INTO departments (title) VALUES (?)",
-1, &dept, nullptr
);
sqlite3_bind_text(dept, 1, "Support", -1, SQLITE_STATIC);
sqlite3_step(dept);
sqlite3_reset(dept);
sqlite3_bind_text(dept, 1, "Archive", -1, SQLITE_STATIC);
sqlite3_step(dept);
sqlite3_finalize(dept);
sqlite3_stmt* member = nullptr;
sqlite3_prepare_v2(
db,
"INSERT INTO staff (dept_id, full_name) VALUES (?, ?)",
-1, &member, nullptr
);
sqlite3_bind_int(member, 1, 1);
sqlite3_bind_text(member, 2, "Alice Gray", -1, SQLITE_STATIC);
sqlite3_step(member);
sqlite3_reset(member);
sqlite3_bind_int(member, 1, 2);
sqlite3_bind_text(member, 2, "Cara Mint", -1, SQLITE_STATIC);
sqlite3_step(member);
sqlite3_finalize(member);
sqlite3_stmt* sel = nullptr;
sqlite3_prepare_v2(
db,
"SELECT s.full_name FROM staff s "
"INNER JOIN departments d ON s.dept_id = d.id "
"WHERE d.title = 'Support'",
-1, &sel, nullptr
);
while (sqlite3_step(sel) == SQLITE_ROW) {
const char* name = reinterpret_cast<const char*>(
sqlite3_column_text(sel, 0)
);
std::cout << name << "\n";
}
sqlite3_finalize(sel);
sqlite3_close(db);
return 0;
}
В join_staff.db добавьте отдел
"Sales" и сотрудника в нем. Выведите
имя и название отдела одной строкой на человека.
Создайте join_fleet.db с таблицами
garages и vehicles. Выведите
номер машины и код гаража для каждой пары.
В join_fleet.db оставьте в выводе
только машины гаража с кодом "G-7".