プロジェクト:シンプルなデータベース
[第]51[課では、アドレス帳システムを作成しました]。
[現在]、[私たちは][2つ目の総合]実践プロジェクト――[簡易データベース]に取り組みます。
[この]プロジェクト[では]C++[の多くの高度な機能]が活用され、[学習成果を試す試金石となる]。
1. プロジェクト[要件]
(1) 1.1 [機能要件]
| [機能] | [説明] |
|---|---|
| CREATE TABLE | [テーブルの作成] |
| INSERT | [データを挿入] |
| SELECT | [データの照会] |
| 場所 | 条件[フィルタ] |
| [索引] | [検索の高速化] |
| [トランザクション] | [ACID保証] |
(2) 1.2 [設計の簡素化]
[教育用の]プロジェクトであるため、[私たちは][簡易版]を作成しました:
- [対応機種]
int[および]stringタイプのみ - [単一テーブルのクエリのみ対応]
- [索]参考文献
std::map[実装] - [データは]メモリ[に]保存されます([オプションで永続化可能])
2. [テーブル構造の設計]
(1) 2.1 [列の定義]
▶ サンプル 2: codeexample (難易度 ⭐)
#include iostream
#include string
#include variant
#include vector
// ...
struct Column {
std::string name;
enum Type { INT, STRING } type;
};
// (variant)
using Value = std::variant<int, std::string>;
// ()
using Row = std::vectorValue;
// ...
class Table {
private:
std::string name;
std::vectorColumn columns;
std::vectorRow rows;
public:
Table(const std::string& name, const std::vectorColumn& columns)
: name(name), columns(columns) {}
// ...
void insert(const Row& row) {
if (row.size() != columns.size()) {
std::cerr << "..." << std::endl;
return;
}
rows.push_back(row);
}
// (:)
std::vectorRow select() {
return rows;
}
// ...
void describe() const {
std::cout << ":" << name << std::endl;
std::cout << ":" << std::endl;
for (const auto& col : columns) {
std::cout << " " << col.name << " (";
if (col.type == Column::INT) {
std::cout << "INT";
} else {
std::cout << "STRING";
}
std::cout << ")" << std::endl;
}
}
};
3. [クエリの実装]
(1) 3.1 WHERE[句]
// (WHERE)
using Predicate = std::function<bool(const Row&)>;
// ...
std::vectorRow selectWhere(Predicate pred) {
std::vectorRow result;
for (const auto& row : rows) {
if (pred(row)) {
result.push_back(row);
}
}
return result;
}
//:age > 18
auto predicate = (const Row& row) {
int age = std::getint(row[1]); // 2age
return age > 18;
};
auto result = table.selectWhere(predicate);
4. [インデックスの実装]
(1) 4.1 [簡易索引]
#include map
// (:int)
class Index {
private:
std::map<int, std::vectorint> index; // ->
public:
void build(const std::vectorRow& rows, int colIndex) {
index.clear();
for (int i = 0; i < rows.size(); i++) {
int key = std::getint(rows[i][colIndex]);
index[key].push_back(i);
}
}
std::vectorint lookup(int key) {
auto it = index.find(key);
if (it != index.end()) {
return it->second;
}
return {};
}
};
5. [トランザクションのサポート]
(1) 5.1 [トランザクションの簡略化]
#include stack
class Transaction {
private:
std::stack<std::vectorRow> undoStack;
public:
// ()
void begin(Table& table) {
undoStack.push(table.rows);
}
// (undo)
void commit() {
while (!undoStack.empty()) {
undoStack.pop();
}
}
// ()
void rollback(Table& table) {
if (!undoStack.empty()) {
table.rows = undoStack.top();
undoStack.pop();
}
}
};
6. [完全版]例
▶ サンプル 1: [簡易データベースの使用] (難易度 ⭐⭐⭐)
int main() {
// ...
Table t("users", {{"name", Column::STRING}, {"age", Column::INT}});
// ...
t.insert({"Alice", 25});
t.insert({"Bob", 30});
t.insert({"Charlie", 20});
// ...
auto rows = t.select();
std::cout << ":" << std::endl;
for (const auto& row : rows) {
std::cout << std::getstd::string(row[0]) << ", "
<< std::getint(row[1]) << std::endl;
}
return 0;
}
7. [今後の展開]
(1) 7.1 [機能拡張]
| [機能] | [難易度] | [説明] |
|---|---|---|
| [永続化] | ⭐⭐ | [保存先]ファイル |
| JOIN | ⭐⭐⭐⭐ | [多表結合] |
| SQL[パーサー] | ⭐⭐⭐⭐⭐ | [解析]SQL[文] |
| [並行制御] | ⭐⭐⭐⭐ | マルチスレッド[安全] |
8. ❓ [練習]
(1) [基礎練習] (難易度 ⭐⭐)
[データベースに]DELETE[機能]を追加する。
(2) [上級練習] (難易度 ⭐⭐⭐)
[データベースに]UPDATE[機能]を追加する。
(3) [チャレンジ問題]([難易度]⭐⭐⭐⭐)
[シンプルな]SQL[パーサー]を実装し、SELECT * FROM table WHERE age > 18に対応する。
❓ よくある質問
Q:practice databaseについて最も重要なことは何ですか? A:まず核心概念を理解し、その後実践的な例で練習することが重要です。
Q:practice databaseを効果的に練習するにはどうすればよいですか? A:簡単な例から始め、徐々に複雑さを増やし、常にコードをテストしてください。
Q:practice databaseでよくある間違いは何ですか? A:コンパイラのエラーメッセージを注意深く読み、変数は使用前に必ず初期化してください。
📖 まとめ
| [知識ポイント] | [応用] |
|---|---|
| バリアント | [異なる]型[の]値 |
| vectorRow | [テーブルデータの格納] |
| マップ | [インデックスの実装] |
| 関数オブジェクト | [実装]WHERE[述語] |
- [簡易データベース]:メモリ[データ] + ファイル[永続化]
- [用] map [を用いて] O(log n) [のキー検索]を実現する
- [CRUDコマンドに対応]インターフェース
- CSV [または] JSON [形式でデータを保存]
- 例外処理[による]プログラム[の安定性]の確保
📝 練習問題
-
初心者(難易度 ⭐): [データベースを実行]し、[「学生テーブル」]([フィールド]:[学籍番号]、[氏名]、[年齢]、[成績])を[作成]し、3[件のレコード]を[挿入]し、[すべてのレコードを照会]する。
-
中級(難易度 ⭐⭐): [追加]「[ソートクエリ]」[機能]――[対応]
SELECT * FROM table ORDER BY [年龄]。[ヒント]:std::sort+ lambda [式] を使用して、指定したフィールドでソートします。 -
上級(難易度 ⭐⭐⭐): [実装]「[複数テーブルの結合]」――[2つのテーブルを作成]([学生テーブル]、[成績テーブル])、
SELECT [学生].[姓名], [成绩].[分数] FROM [学生] JOIN [成绩] ON [学生].[学号] = [成绩].[学号]を[サポート]。[設計が必要] JOIN [論理結合と結果セットの結合]。
[次のレッスン]:[コースのまとめと次のステップ](#53)



