メインコンテンツにスキップ

💾 データベースとは?

📖 定義

データベース(Database, DB)は体系的に構造化されたデータの集合です。DBMS(Database Management System、データベース管理システム)は、データベースを作成、管理、アクセスするソフトウェアです。データベースはデータを効率的に保存・検索でき、複数のユーザーが同時に安全にアクセスできます。

🎯 比喩で理解する

図書館システム

データベースを図書館に例えると:

  • データベース: 図書館全体
  • テーブル: 各セクション(小説、科学、歴史など)
  • 行(Row): 個別の本
  • 列(Column): 本の属性(タイトル、著者、出版年など)
  • 主キー(Primary Key): 図書固有番号
  • DBMS: 司書と管理システム
図書館 (データベース)
├─ 小説セクション (テーブル)
│ ├─ 本1: ハリーポッター, J.K.ローリング, 1997
│ ├─ 本2: 指輪物語, トールキン, 1954
│ └─ 本3: 星の王子さま, サン=テグジュペリ, 1943
├─ 科学セクション (テーブル)
│ ├─ 本1: コスモス, カール・セーガン, 1980
│ └─ 本2: 利己的な遺伝子, リチャード・ドーキンス, 1976
└─ 貸出記録 (テーブル)
├─ 記録1: 会員123, ハリーポッター, 2024-01-15
└─ 記録2: 会員456, コスモス, 2024-01-20

⚙️ 動作原理

1. データベース構造

データベース (Database)
└─ テーブル (Table)
├─ 行 (Row/Record) - 個別データ項目
│ └─ 例: 一人のユーザー情報
└─ 列 (Column/Field) - データ属性
└─ 例: 名前、メール、年齢

2. リレーショナルデータベースの例

-- usersテーブル
users
┌────┬────────┬──────────────────┬─────┐
│ id │ name │ email │ age │
├────┼────────┼──────────────────┼─────┤
1 │ 山田 │ yamada@mail.com25
2 │ 佐藤 │ sato@mail.com30
3 │ 鈴木 │ suzuki@mail.com28
└────┴────────┴──────────────────┴─────┘

-- ordersテーブル
orders
┌────┬─────────┬─────────────┬───────┐
│ id │ user_id │ product │ price │
├────┼─────────┼─────────────┼───────┤
11 │ ノートPC │ 1500
21 │ マウス │ 30
32 │ キーボード │ 80
└────┴─────────┴─────────────┴───────┘

└─ 外部キー: usersテーブルのidを参照

3. CRUD操作

CRUDはデータベースの4つの基本操作です:

C - Create  (作成): 新しいデータを追加
R - Read (読取): データを照会
U - Update (更新): 既存データを変更
D - Delete (削除): データを削除

💡 実例

SQLでCRUD操作

-- CREATE (作成): テーブル作成
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- CREATE (作成): データ追加
INSERT INTO users (name, email, age)
VALUES ('山田太郎', 'yamada@mail.com', 25);

INSERT INTO users (name, email, age)
VALUES
('佐藤花子', 'sato@mail.com', 30),
('鈴木一郎', 'suzuki@mail.com', 28);

-- READ (読取): 全ユーザー照会
SELECT * FROM users;

-- READ (読取): 条件付き照会
SELECT name, email FROM users
WHERE age >= 28;

-- READ (読取): ソートして照会
SELECT * FROM users
ORDER BY age DESC;

-- READ (読取): 検索
SELECT * FROM users
WHERE name LIKE '山田%';

-- UPDATE (更新): データ変更
UPDATE users
SET age = 26
WHERE name = '山田太郎';

-- UPDATE (更新): 複数フィールド修正
UPDATE users
SET email = 'new@mail.com', age = 31
WHERE id = 2;

-- DELETE (削除): データ削除
DELETE FROM users
WHERE id = 3;

-- DELETE (削除): 条件付き削除
DELETE FROM users
WHERE age < 20;

Node.jsでのデータベース使用

const mysql = require('mysql2/promise');

// データベース接続
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
waitForConnections: true,
connectionLimit: 10
});

// CREATE - ユーザー追加
async function createUser(name, email, age) {
const [result] = await pool.execute(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
[name, email, age]
);
console.log('作成されたID:', result.insertId);
return result.insertId;
}

// READ - 全ユーザー取得
async function getAllUsers() {
const [rows] = await pool.execute('SELECT * FROM users');
return rows;
}

// READ - 特定ユーザー取得
async function getUserById(id) {
const [rows] = await pool.execute(
'SELECT * FROM users WHERE id = ?',
[id]
);
return rows[0];
}

// UPDATE - ユーザー情報更新
async function updateUser(id, name, email, age) {
const [result] = await pool.execute(
'UPDATE users SET name = ?, email = ?, age = ? WHERE id = ?',
[name, email, age, id]
);
console.log('更新された行:', result.affectedRows);
return result.affectedRows;
}

// DELETE - ユーザー削除
async function deleteUser(id) {
const [result] = await pool.execute(
'DELETE FROM users WHERE id = ?',
[id]
);
console.log('削除された行:', result.affectedRows);
return result.affectedRows;
}

// 使用例
async function main() {
try {
// 作成
const userId = await createUser('山田太郎', 'yamada@mail.com', 25);

// 照会
const users = await getAllUsers();
console.log('全ユーザー:', users);

// 特定ユーザー照会
const user = await getUserById(userId);
console.log('特定ユーザー:', user);

// 更新
await updateUser(userId, '山田太郎', 'new@mail.com', 26);

// 削除
await deleteUser(userId);
} catch (error) {
console.error('エラー:', error);
}
}

main();

ORM使用 (Sequelize)

const { Sequelize, DataTypes } = require('sequelize');

// データベース接続
const sequelize = new Sequelize('myapp', 'root', 'password', {
host: 'localhost',
dialect: 'mysql'
});

// モデル定義 (テーブル構造)
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true
},
age: {
type: DataTypes.INTEGER
}
});

// CRUD操作 (SQLなしでJavaScriptのみ!)
async function ormExample() {
// CREATE - 作成
const user = await User.create({
name: '山田太郎',
email: 'yamada@mail.com',
age: 25
});
console.log('作成:', user.toJSON());

// READ - 照会
const allUsers = await User.findAll();
console.log('全ユーザー:', allUsers);

// READ - 条件照会
const youngUsers = await User.findAll({
where: { age: { [Sequelize.Op.gte]: 20 } },
order: [['age', 'DESC']]
});

// READ - 1つ照会
const oneUser = await User.findOne({
where: { email: 'yamada@mail.com' }
});

// UPDATE - 更新
await User.update(
{ age: 26 },
{ where: { name: '山田太郎' } }
);

// DELETE - 削除
await User.destroy({
where: { id: 1 }
});
}

リレーション設定 (JOIN)

// ユーザーと注文のリレーション設定
const User = sequelize.define('User', {
name: DataTypes.STRING,
email: DataTypes.STRING
});

const Order = sequelize.define('Order', {
product: DataTypes.STRING,
price: DataTypes.DECIMAL(10, 2)
});

// リレーション定義: 1人のユーザーは複数の注文が可能
User.hasMany(Order);
Order.belongsTo(User);

// JOINクエリ
async function getUserWithOrders(userId) {
const userWithOrders = await User.findOne({
where: { id: userId },
include: Order // JOIN
});

console.log(userWithOrders.toJSON());
// {
// id: 1,
// name: '山田太郎',
// email: 'yamada@mail.com',
// Orders: [
// { product: 'ノートPC', price: 1500 },
// { product: 'マウス', price: 30 }
// ]
// }
}

🤔 よくある質問

Q1. データベースを使う理由は?

A: ファイルシステムより多くの利点があります:

❌ ファイルシステム (例: users.txt)
├─ データの重複可能
├─ 同時アクセス問題
├─ バックアップ/復旧困難
├─ セキュリティ脆弱
└─ 検索遅い

✅ データベース
├─ データ整合性保証
├─ 同時実行制御 (複数ユーザー)
├─ バックアップ/復旧自動化
├─ アクセス権限管理
├─ 高速検索 (インデックス)
└─ トランザクションサポート

Q2. どのデータベースを選ぶべき?

A: プロジェクト要件によって異なります:

// リレーショナルデータベース (SQL)
MySQL / PostgreSQL / SQLite
├─ 長所: 正確なデータ構造、トランザクション
├─ 短所: 柔軟性低い、拡張性制限
└─ 適合: 金融、電子商取引、ユーザー管理

// 非リレーショナルデータベース (NoSQL)
MongoDB / Redis / Cassandra
├─ 長所: 柔軟なスキーマ、水平拡張
├─ 短所: 複雑な関係処理困難
└─ 適合: ソーシャルメディア、リアルタイム分析、キャッシング

Q3. インデックス(Index)とは?

A: データ検索速度を向上させるデータ構造です:

-- インデックスなし
SELECT * FROM users WHERE email = 'test@mail.com';
-- → 100万行すべて確認 (遅い)

-- インデックス作成
CREATE INDEX idx_email ON users(email);

-- インデックスあり
SELECT * FROM users WHERE email = 'test@mail.com';
-- → インデックスで直接検索 (速い!)

-- 欠点: データ挿入/更新時にインデックスも更新 (書込み遅くなる)

比喩: 本の目次や索引のように、欲しい内容を素早く見つけられるようにしてくれます。

Q4. トランザクション(Transaction)とは?

A: 複数の操作を1つの単位としてまとめて処理すること:

// 銀行送金の例
async function transferMoney(fromId, toId, amount) {
const connection = await pool.getConnection();

try {
// トランザクション開始
await connection.beginTransaction();

// 1. 送信者の残高減少
await connection.execute(
'UPDATE accounts SET balance = balance - ? WHERE id = ?',
[amount, fromId]
);

// 2. 受信者の残高増加
await connection.execute(
'UPDATE accounts SET balance = balance + ? WHERE id = ?',
[amount, toId]
);

// すべて成功 → 確定
await connection.commit();
console.log('送金完了!');

} catch (error) {
// エラー発生 → すべてキャンセル
await connection.rollback();
console.log('送金失敗、ロールバック');
throw error;
} finally {
connection.release();
}
}

// ACID原則
// Atomicity (原子性): すべて実行 or すべてキャンセル
// Consistency (一貫性): ルール違反なし
// Isolation (独立性): 他のトランザクションと独立
// Durability (永続性): 完了後永久保存

Q5. SQL Injectionとは?

A: 悪意のあるSQLコードを注入する攻撃です:

// ❌ 危険なコード (SQL Injection脆弱)
const email = req.body.email; // "admin@mail.com' OR '1'='1"
const query = `SELECT * FROM users WHERE email = '${email}'`;
// 実行: SELECT * FROM users WHERE email = 'admin@mail.com' OR '1'='1'
// → 全ユーザー情報漏洩!

// ✅ 安全なコード (Prepared Statement)
const [rows] = await pool.execute(
'SELECT * FROM users WHERE email = ?',
[email] // 自動的にエスケープされる
);

// ORM使用 (自動防御)
const user = await User.findOne({
where: { email: email } // 安全
});

🎓 次のステップ

データベースを理解したら、次を学習してみましょう:

  1. SQL vs NoSQL - データベース選択ガイド
  2. Node.jsとは? - バックエンド開発
  3. APIとは? - データベースとフロントエンドの接続

実習してみる

# MySQL インストールと実行
brew install mysql # macOS
sudo apt install mysql # Linux

# データベース接続
mysql -u root -p

# データベース作成
CREATE DATABASE myapp;
USE myapp;

# テーブル作成とデータ追加
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
email VARCHAR(100)
);

INSERT INTO users (name, email) VALUES ('山田太郎', 'test@mail.com');
SELECT * FROM users;

🎬 まとめ

データベースはすべてのアプリケーションの核心です:

  • データベース: 構造化されたデータ集合
  • CRUD: 作成、読取、更新、削除 - 基本操作
  • テーブル: 行と列でデータを構造化
  • リレーション: テーブル間の接続 (JOIN)
  • トランザクション: 安全なデータ処理

データベースをよく理解すれば、安定した拡張可能なアプリケーションを構築できます! 💾✨