このレッスンでは、データベースについて学びます。
データベース とは、大量の情報を整理し、一貫性を保ちながら保存・検索・更新するためのソフトウェアです。大量のデジタルデータを扱うアプリケーションや業務には欠かせない存在です。
ここではデータベースとは何か、特徴や基本的な仕組み、設計方法について説明します。また、実際にデータベースの操作を試してみることで理解を深めます。
このレッスンを通して、データベースの仕組みに対する正しいイメージを持ち、ビジネスシーンでのデータ活用をイメージできるようになりましょう。
データベースの基礎や設計・運用の考え方、SQLの基本操作を理解し、ビジネスシーンでのデータ活用をイメージできるようになること
企業では、顧客名簿や受注履歴、在庫リスト、従業員情報など、多種多様なデータを日々取り扱います。
これらを個人のパソコンやExcelファイルで管理していると、関係者が同じ情報を共有できなかったり、更新漏れによって不整合が起こったりする恐れがあります。データベースはこの問題を解決し、組織全体で一元的にデータを活用する土台を提供します。
データベースは データを永続的に保存 するのに適しています。
データベースは、単にデータを入れておくだけの「箱」ではありません。以下のような、検索や更新などの操作を円滑に行なうための仕組みが組み込まれています。
DBMS(データベース管理システム:DataBase Management System)は、データベースを作成・管理するためのソフトウェアです。
データベースとDBMSは、よくひとまとめに「データベース」と呼ばれがちですが、本来は次のように区別されます。
DBMSが提供する主な機能は次のとおりです。
DBMSがデータベースを仲介して管理するイメージ
代表的なDBMS製品には、以下のようなものがあります。
リレーショナルデータベース(RDB)は、データをテーブル形式で管理するデータベースです。リレーショナルデータベースを管理するシステムを、リレーショナルデータベース管理システム(RDBMS)と呼びます。
リレーショナルデータベースは、データベースのなかで最も広く使われており、多くの業務システムやWebサービスのバックエンドで採用されています。
リレーショナルデータベースの構成は、基本的に1つのアプリケーションに対して1つのデータベースがあり、1つのデータベースの中に複数のテーブル(表)があります。
1つ1つのテーブル(表)は、Excelのシートと同じように縦横の表となっています。
Excelで例えると、Excelファイルが1つのデータベースであり、その中にある複数のシートがテーブル、シートの中の1つ1つのセルが具体的なデータとなるイメージです。

リレーショナルデータベースには、以下の特徴があります。
テーブルは横と縦で構成され、横方向の要素を レコード(行)、縦方向の要素を カラム(列)と呼びます。
レコードは実際のデータの実体、カラムはデータの項目名や属性を示します。
下記のテーブルであれば、ユーザーテーブルのレコードは3件あり、「idカラムの値」が 2 のレコードの、「nameカラムの値」は 次郎 となります。

テーブル内のレコードとカラム
データ型 は、格納するデータ形式を定義するものです。
下記のテーブルであれば、idには int という整数型が、nameには varchar という文字列型が設定されています。カラムで指定された型以外の値を含んだレコードは保存が失敗するようになっています。

テーブル内のカラムにおけるデータ型
制約 とは、テーブルのカラム(列)に対して課すルールや制約条件です。
データベースはデータを一元管理しているので、データの整合性や一貫性が求められ、データの不整合がおきてはなりません。制約を設定することによって、カラムの値が不適切にならないよう、データの整合性や品質を保てるようになります。
主な制約には以下があります。
NULL 以外である(空値を許可しない)という制約です。NULL は、空値(値がない)という意味です。NOW() をデフォルトで設定する。リレーショナルデータベースでは、「SQL」というデータベースのための言語を使用して命令文を記述し、データの保存や取得を行ないます。たとえばユーザーテーブル(users)から全員分の名前(name)を取得するには、下記のような命令文となります。
select name from users;
それでは、SQLについて学んでいきましょう。
SQL(エスキューエル:Structured Query Language)は、主にリレーショナルデータベースを操作するための「問い合わせ言語」です。
SQLには、大きく3つの役割があります。
CREATE や ALTER、DROP などが該当します。SELECT、INSERT、UPDATE、DELETE が代表的な例です。GRANT、REVOKE、COMMIT、ROLLBACK などがあります。ここでは主に使用する、データ定義(DDL)とデータ操作(DML)のSQLについて説明します。
ここでは、以下のSQLを紹介します。
データベースの作成は CREATE DATABASE 文を使用します。
書式:
CREATE DATABASE データベース名 [オプション]
オプションは、DBMSによって異なります。たとえば、MySQLでは以下のような指定を行ないます。
CREATE DATABASE データベース名 CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
CHARACTER SET utf8mb4 COLLATE utf8mb4_bin の部分は、データベースで日本語を扱う際に一般的に使用される設定です。データベースの削除は DROP DATABASE 文を使用します。
書式:
DROP DATABASE データベース名;
このSQLは 確認なしでデータベースを即削除 します。そのため、実務では管理者の許可なしにこれを実行することは絶対に避けて ください。どんなに大量のデータがあっても、一瞬で完全に消去されてしまいます。
テーブルの作成は CREATE TABLE 文を使用します。
書式:
CREATE TABLE テーブル名 ( 列名 型 オプション, 列名 型 オプション, ... );
テーブルの削除は DROP TABLE 文を使用します。
書式:
DROP TABLE テーブル名;
このSQLは 確認なしでテーブルを即削除 します。そのため、実務では管理者の許可なしにこれを実行することは絶対に避けて ください。どんなに大量のデータがあっても、一瞬で完全に消去されてしまいます。
基本的なデータ操作には、次の4つがあります。これらをまとめてCRUD(クラッド)と呼びます。
| 操作 | 日本語 | SQL |
|---|---|---|
| Create | 作成・保存 | INSERT |
| Read | 取得 | SELECT |
| Update | 更新 | UPDATE |
| Delete | 削除 | DELETE |
順番に確認していきましょう。
INSERT は、テーブルに新しい行を挿入するための命令です。基本的な書式は以下のとおりです。
INSERT INTO テーブル名 (列名1, 列名2, ...) VALUES (値1, 値2, ...);
たとえば「顧客テーブル」にデータを追加する際は、以下のように書きます。
INSERT INTO 顧客 (顧客ID, 氏名, 住所, 電話番号) VALUES (1004, '鈴木 次郎', '神奈川県横浜市...', '045-xxxx-xxxx');
テーブルの列定義と挿入するデータの順番や型はそろえる必要があります。挿入が完了すると新しいレコードが追加され、SELECT文で参照できるようになります。
SELECT は、テーブルから必要なレコードを取り出すための命令です。基本的な書式は以下のとおりです。
SELECT 列名1, 列名2, ... FROM テーブル名 [WHERE 条件];
列名1, 列名2, ... の部分には、取得したい列を指定します。すべて取得する場合は * を使えます。FROM テーブル名 で対象のテーブルを指定します。WHERE 条件 はオプションです。つけることで、特定の条件を満たす行のみを抽出できます。たとえば「顧客テーブル」から 氏名 列と 電話番号 列だけを抽出したい場合は次のように書きます。
SELECT 氏名, 電話番号 FROM 顧客;
在住地域が「東京都」の顧客だけを抽出したければ、以下のように WHERE 句を追加します。
SELECT 氏名, 電話番号 FROM 顧客 WHERE 住所 LIKE '東京都%';
UPDATE は、既存の行の値を変更するための命令です。基本的な書式は以下のとおりです。
UPDATE テーブル名 SET 列名1 = 値1, 列名2 = 値2, ... WHERE 条件;
たとえば「顧客テーブル」で 顧客ID = 1002 の行に対して 住所 列を変更したい場合、以下のようになります。
UPDATE 顧客 SET 住所 = '埼玉県さいたま市〇〇...' WHERE 顧客ID = 1002;
WHERE を指定しないと、すべての行が更新対象となる点に注意が必要です。
DELETE は、テーブルから不要なデータを削除するための命令です。基本的な書式は以下のとおりです。
DELETE FROM テーブル名 WHERE 条件;
たとえば、顧客ID = 1003 の顧客情報を削除したい場合は以下のように書きます。
DELETE FROM 顧客 WHERE 顧客ID = 1003;
これも WHERE をつけないと、テーブル内のすべての行が削除されるため、注意が必要です。特に本番環境で実行するときは、慎重に条件を確認する必要があります。
SQLは単にデータを挿入・更新・削除するだけでなく、複数のテーブルを結合して集計したり、特定の条件に合うレコードだけを取り出したりといった高度な処理を行なえます。ここでは代表的な機能を紹介します。
前述したように、WHERE 句を使えば指定した条件を満たす行だけを抽出できます。条件式は = や >、< などの演算子や LIKE、BETWEEN、IN などを組み合わせることで、柔軟に設計できます。複数の条件を組み合わせる場合は AND や OR を使って論理演算を行ないます。
SELECT * FROM 顧客 WHERE 住所 LIKE '東京%' AND 登録日 >= '2023-01-01';
上記例では、住所が「東京」で始まり、かつ登録日が2023年1月1日以降の顧客のみを取得します。
GROUP BY 句を使うと、テーブルのデータを特定の列でグループ化して集計することができます。たとえば「注文」テーブルにおいて、日付ごとの売上合計金額を集計する場合は、次のようになります。
SELECT 注文日, SUM(金額) AS 日次売上 FROM 注文 GROUP BY 注文日;
ここで SUM のような 集計関数 が利用できます。代表的なものは次のとおりです。
SUM():数値型の合計値を求めるCOUNT():行数を数えるAVG():数値型の平均値を求めるMAX():最大値を求めるMIN():最小値を求めるさらに GROUP BY と HAVING を組み合わせることで、グループ化したあとに追加の条件でフィルタリングをかけることができます。たとえば「売上が一定額を超える日だけ見たい」という場合、集計結果に対して HAVING SUM(金額) > 100000 のような条件を指定できます。
複数のテーブルに分散しているデータをまとめて取得するには JOIN が必要です。JOINを使えば、テーブル同士の外部キーなどをもとに、1つの大きな結果セットとして表示できます。以下は JOIN の代表的な種類です。
NULL が入ります。たとえば「顧客」テーブルと「注文」テーブルを連結して、顧客氏名と注文日、注文金額をまとめて取得したい場合は次のように書きます。
SELECT 顧客.氏名, 注文.注文日, 注文.金額 FROM 顧客 INNER JOIN 注文 ON 顧客.顧客ID = 注文.顧客ID;
ここで 顧客ID が両テーブルを結びつける外部キーです。INNER JOIN はあくまで一致する行だけを表示するため、注文がない顧客は結果に出てきません。注文のない顧客も含めたい場合は、LEFT JOIN を使うとよいです。
JOINを活用することで、複雑なデータ分析やレポート作成が容易になります。複数のテーブルから一気に情報を引き出し、集計やソートを行なうなど、柔軟なデータ処理が可能です。
それでは、実際にプログラミングを体験してみましょう。
ここでは、顧客テーブル(customers)を作成し、CRUD(Create, Read, Update, Delete)の一連の操作を行なう流れを示します。
さらに、その次のステップとして、注文テーブル(orders)を作成してテーブル同士の関連性を定義し、フィルタリングやグループ化、JOINによる結合を体験します。
今回も paiza.io を利用します。


通常のデータベースは、テーブルの作成やデータを追加した内容は永続化されて保存されますが、paiza.ioは、永続化が行なわれません。
そのため以降のSQLでは、毎回テーブルの作成から行なっていますが、paiza.io特有の書き方としてご認識ください。
まずは、顧客情報を管理する customers テーブルを作成します。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE );
-- で始まる -- 顧客テーブルの作成 はコメントです。customer_id は主キーとして設定し、一意に顧客を特定します。name、address、phone、registered_date は必要な顧客情報を想定しています。
name:顧客名address:住所phone:電話番号registered_date:登録日DATE 型を使います。時間まで必要なら DATETIME を使います。実行結果:
ここでの出力はありません。
次に、データの登録や更新、削除、検索を行なってみましょう。
ここで示す4つの操作が、RDB(リレーショナルデータベース)で頻繁に利用される基本機能です。
テーブルに新規レコードを追加するには、INSERT文を使います。サンプルとして、4件のデータを追加します。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE ); -- データの追加 INSERT INTO customers VALUES (1001, '田中 太郎', '東京都千代田区〇〇', '03-1234-5678', '2024-01-10'); INSERT INTO customers VALUES (1002, '山田 花子', '神奈川県横浜市〇〇', '045-9876-5432', '2024-01-15'); INSERT INTO customers VALUES (1003, 'John Smith', 'Tokyo, Japan', '090-1111-2222', '2024-01-20'); INSERT INTO customers VALUES (1004, '鈴木 次郎', '埼玉県さいたま市〇〇', '048-5555-6666', '2024-02-01');
実行すると、顧客テーブルに4件のデータが登録されます。INSERT文では、列名と値の順序・データ型を合わせることが基本です。
実行結果:
ここでの出力はありません。
登録されたデータを確認するには、SELECT文を使います。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE ); -- データの追加 INSERT INTO customers VALUES (1001, '田中 太郎', '東京都千代田区〇〇', '03-1234-5678', '2024-01-10'); INSERT INTO customers VALUES (1002, '山田 花子', '神奈川県横浜市〇〇', '045-9876-5432', '2024-01-15'); INSERT INTO customers VALUES (1003, 'John Smith', 'Tokyo, Japan', '090-1111-2222', '2024-01-20'); INSERT INTO customers VALUES (1004, '鈴木 次郎', '埼玉県さいたま市〇〇', '048-5555-6666', '2024-02-01'); -- データの読み取り SELECT * FROM customers;
実行結果:
customer_id name address phone registered_date
1001 田中 太郎 東京都千代田区〇〇 03-1234-5678 2024-01-10
1002 山田 花子 神奈川県横浜市〇〇 045-9876-5432 2024-01-15
1003 John Smith Tokyo, Japan 090-1111-2222 2024-01-20
1004 鈴木 次郎 埼玉県さいたま市〇〇 048-5555-6666 2024-02-01
特定の列だけを抽出したい場合は、* の代わりに列名を指定します。また、WHERE句を使えば、条件に合致する行だけを抽出できます。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE ); -- データの追加 INSERT INTO customers VALUES (1001, '田中 太郎', '東京都千代田区〇〇', '03-1234-5678', '2024-01-10'); INSERT INTO customers VALUES (1002, '山田 花子', '神奈川県横浜市〇〇', '045-9876-5432', '2024-01-15'); INSERT INTO customers VALUES (1003, 'John Smith', 'Tokyo, Japan', '090-1111-2222', '2024-01-20'); INSERT INTO customers VALUES (1004, '鈴木 次郎', '埼玉県さいたま市〇〇', '048-5555-6666', '2024-02-01'); -- 特定の列だけを抽出 SELECT customer_id, name FROM customers WHERE address LIKE '%東京%';
実行結果:
customer_id name
1001 田中 太郎
レコードを修正したい場合は、UPDATE文を使います。たとえば 顧客ID = 1003 の 住所 を変更する例を示します。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE ); -- データの追加 INSERT INTO customers VALUES (1001, '田中 太郎', '東京都千代田区〇〇', '03-1234-5678', '2024-01-10'); INSERT INTO customers VALUES (1002, '山田 花子', '神奈川県横浜市〇〇', '045-9876-5432', '2024-01-15'); INSERT INTO customers VALUES (1003, 'John Smith', 'Tokyo, Japan', '090-1111-2222', '2024-01-20'); INSERT INTO customers VALUES (1004, '鈴木 次郎', '埼玉県さいたま市〇〇', '048-5555-6666', '2024-02-01'); -- データの更新 UPDATE customers SET address = 'Meguro, Tokyo' WHERE customer_id = 1003; -- 更新されたことを確認 SELECT * FROM customers;
WHERE句を指定しないと、テーブル内の全データが更新されてしまうため注意が必要です。
実行結果:
customer_id name address phone registered_date
1001 田中 太郎 東京都千代田区〇〇 03-1234-5678 2024-01-10
1002 山田 花子 神奈川県横浜市〇〇 045-9876-5432 2024-01-15
1003 John Smith Meguro, Tokyo 090-1111-2222 2024-01-20
1004 鈴木 次郎 埼玉県さいたま市〇〇 048-5555-6666 2024-02-01
不要なデータを削除するには、DELETE文を用います。たとえば、顧客ID = 1004 のデータを削除する場合は次のように書きます。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE ); -- データの追加 INSERT INTO customers VALUES (1001, '田中 太郎', '東京都千代田区〇〇', '03-1234-5678', '2024-01-10'); INSERT INTO customers VALUES (1002, '山田 花子', '神奈川県横浜市〇〇', '045-9876-5432', '2024-01-15'); INSERT INTO customers VALUES (1003, 'John Smith', 'Tokyo, Japan', '090-1111-2222', '2024-01-20'); INSERT INTO customers VALUES (1004, '鈴木 次郎', '埼玉県さいたま市〇〇', '048-5555-6666', '2024-02-01'); -- データの削除 DELETE FROM customers WHERE customer_id = 1004; -- 削除されたことを確認 SELECT * FROM customers;
これもUPDATEと同様、WHERE句をつけないと全行削除の可能性があるため、実運用では慎重に扱う必要があります。
実行結果:
customer_id name address phone registered_date
1001 田中 太郎 東京都千代田区〇〇 03-1234-5678 2024-01-10
1002 山田 花子 神奈川県横浜市〇〇 045-9876-5432 2024-01-15
1003 John Smith Tokyo, Japan 090-1111-2222 2024-01-20
複数テーブルを扱うために、注文を管理する orders テーブルを作成します。customers テーブルとの関係を示すために、外部キーとして customer_id を設定するのがポイントです。あわせて、このテーブルにいくつかサンプルデータを挿入します。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE ); -- データの追加 INSERT INTO customers VALUES (1001, '田中 太郎', '東京都千代田区〇〇', '03-1234-5678', '2024-01-10'); INSERT INTO customers VALUES (1002, '山田 花子', '神奈川県横浜市〇〇', '045-9876-5432', '2024-01-15'); INSERT INTO customers VALUES (1003, 'John Smith', 'Tokyo, Japan', '090-1111-2222', '2024-01-20'); INSERT INTO customers VALUES (1004, '鈴木 次郎', '埼玉県さいたま市〇〇', '048-5555-6666', '2024-02-01'); -- 注文テーブルの作成 CREATE TABLE orders ( order_id INT PRIMARY KEY, customer_id INT, order_date DATE, product_name VARCHAR(50), amount INT, CONSTRAINT fk_customer FOREIGN KEY (customer_id) REFERENCES customers (customer_id) ); -- データの追加 INSERT INTO orders (order_id, customer_id, order_date, product_name, amount) VALUES (2001, 1001, '2024-02-10', 'ノートPC', 80000), (2002, 1001, '2024-03-01', 'マウス', 2000), (2003, 1002, '2024-03-15', 'モニター', 20000), (2004, 1003, '2024-03-20', 'キーボード', 5000), (2005, 1003, '2024-03-25', 'プリンター', 20000);
注文テーブルの作成について:
order_id は主キーとして新規の注文を識別します。customer_id は customers テーブルの customer_id と関連づける外部キーです。order_date、product_name、amount は注文内容を表す列です。orders に存在する customer_id は、必ず customers テーブルに存在していなければなりません。データの追加について:
VALUES (...) , (...) とカンマ区切りで連続して指定できます。実行結果:
ここでの出力はありません。
最後に、少し実践的なSQL操作を試してみます。具体的には、WHERE 句を使った絞り込みや GROUP BY を使った集計、複数テーブルを結合するJOINの操作を確認します。
まずは、注文テーブルから、金額が1万円以上の注文のみを抽出する例です。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE ); -- データの追加 INSERT INTO customers VALUES (1001, '田中 太郎', '東京都千代田区〇〇', '03-1234-5678', '2024-01-10'); INSERT INTO customers VALUES (1002, '山田 花子', '神奈川県横浜市〇〇', '045-9876-5432', '2024-01-15'); INSERT INTO customers VALUES (1003, 'John Smith', 'Tokyo, Japan', '090-1111-2222', '2024-01-20'); INSERT INTO customers VALUES (1004, '鈴木 次郎', '埼玉県さいたま市〇〇', '048-5555-6666', '2024-02-01'); -- 注文テーブルの作成 CREATE TABLE orders ( order_id INT PRIMARY KEY, customer_id INT, order_date DATE, product_name VARCHAR(50), amount INT, CONSTRAINT fk_customer FOREIGN KEY (customer_id) REFERENCES customers (customer_id) ); -- データの追加 INSERT INTO orders (order_id, customer_id, order_date, product_name, amount) VALUES (2001, 1001, '2024-02-10', 'ノートPC', 80000), (2002, 1001, '2024-03-01', 'マウス', 2000), (2003, 1002, '2024-03-15', 'モニター', 20000), (2004, 1003, '2024-03-20', 'キーボード', 5000), (2005, 1003, '2024-03-25', 'プリンター', 20000); -- フィルタリング SELECT * FROM orders WHERE amount >= 10000;
結果として、合計金額が高い注文だけをリストアップできます。必要に応じて日付条件を組み合わせるなどして、柔軟なフィルタリングが可能です。
実行結果:
order_id customer_id order_date product_name amount
2001 1001 2024-02-10 ノートPC 80000
2003 1002 2024-03-15 モニター 20000
2005 1003 2024-03-25 プリンター 20000
GROUP BY 句を使い、顧客ごとの注文合計金額を集計してみます。どの顧客が最も多くの注文をしているかなどの分析に役立ちます。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE ); -- データの追加 INSERT INTO customers VALUES (1001, '田中 太郎', '東京都千代田区〇〇', '03-1234-5678', '2024-01-10'); INSERT INTO customers VALUES (1002, '山田 花子', '神奈川県横浜市〇〇', '045-9876-5432', '2024-01-15'); INSERT INTO customers VALUES (1003, 'John Smith', 'Tokyo, Japan', '090-1111-2222', '2024-01-20'); INSERT INTO customers VALUES (1004, '鈴木 次郎', '埼玉県さいたま市〇〇', '048-5555-6666', '2024-02-01'); -- 注文テーブルの作成 CREATE TABLE orders ( order_id INT PRIMARY KEY, customer_id INT, order_date DATE, product_name VARCHAR(50), amount INT, CONSTRAINT fk_customer FOREIGN KEY (customer_id) REFERENCES customers (customer_id) ); -- データの追加 INSERT INTO orders (order_id, customer_id, order_date, product_name, amount) VALUES (2001, 1001, '2024-02-10', 'ノートPC', 80000), (2002, 1001, '2024-03-01', 'マウス', 2000), (2003, 1002, '2024-03-15', 'モニター', 20000), (2004, 1003, '2024-03-20', 'キーボード', 5000), (2005, 1003, '2024-03-25', 'プリンター', 20000); -- GROUP BYを使った集計 SELECT customer_id, SUM(amount) AS total_amount FROM orders GROUP BY customer_id;
ここでは SUM() 関数を用いて金額列を合計しています。同様に、COUNT(*) や AVG(amount) など、さまざまな集計を行なうこともできます。
実行結果:
customer_id total_amount
1001 82000
1002 20000
1003 25000
最後に、顧客テーブルと注文テーブルを結合して、顧客情報と注文情報を同時に表示する例を示します。両テーブルを関連づける外部キーとして customer_id を使います。
-- 顧客テーブルの作成 CREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(50), address VARCHAR(100), phone VARCHAR(20), registered_date DATE ); -- データの追加 INSERT INTO customers VALUES (1001, '田中 太郎', '東京都千代田区〇〇', '03-1234-5678', '2024-01-10'); INSERT INTO customers VALUES (1002, '山田 花子', '神奈川県横浜市〇〇', '045-9876-5432', '2024-01-15'); INSERT INTO customers VALUES (1003, 'John Smith', 'Tokyo, Japan', '090-1111-2222', '2024-01-20'); INSERT INTO customers VALUES (1004, '鈴木 次郎', '埼玉県さいたま市〇〇', '048-5555-6666', '2024-02-01'); -- 注文テーブルの作成 CREATE TABLE orders ( order_id INT PRIMARY KEY, customer_id INT, order_date DATE, product_name VARCHAR(50), amount INT, CONSTRAINT fk_customer FOREIGN KEY (customer_id) REFERENCES customers (customer_id) ); -- データの追加 INSERT INTO orders (order_id, customer_id, order_date, product_name, amount) VALUES (2001, 1001, '2024-02-10', 'ノートPC', 80000), (2002, 1001, '2024-03-01', 'マウス', 2000), (2003, 1002, '2024-03-15', 'モニター', 20000), (2004, 1003, '2024-03-20', 'キーボード', 5000), (2005, 1003, '2024-03-25', 'プリンター', 20000); -- テーブル結合 SELECT c.name AS customer_name, o.order_id, o.product_name, o.amount FROM customers c INNER JOIN orders o ON c.customer_id = o.customer_id;
INNER JOIN は両テーブルに共通して存在するキーのみを表示するため、注文がない顧客は結果に含まれません。注文がない顧客も一覧に表示したい場合は、LEFT JOIN を使えば、顧客テーブルのレコードをすべて含める形にできます。
JOINを使うことで、複数のテーブルを論理的に一体化し、必要な情報を一度に抽出できます。システムが複雑化するほど、テーブル同士の関連付けが増えるため、JOINを活用する頻度も高まります。WHERE句やGROUP BY句と組み合わせれば、よりきめ細かな分析が可能です。
実行結果:
customer_name order_id product_name amount
田中 太郎 2001 ノートPC 80000
田中 太郎 2002 マウス 2000
山田 花子 2003 モニター 20000
John Smith 2004 キーボード 5000
John Smith 2005 プリンター 20000
データベース設計 は、ビジネス要件をもとに、テーブル構造やデータ型、インデックス、トランザクション管理などを決定する工程です。
適切に設計されたデータベースは、効率的な検索と更新を可能にし、障害が発生したときのリカバリも容易にしてくれます。逆に、要件定義が不十分だったり、テーブル定義が複雑すぎたりすると、データの不整合やパフォーマンス低下、保守運用のコスト増大につながる恐れがあります。
こうしたリスクを回避するために、データベース設計のポイントを押さえ、どんなデータをどのように扱うのかを明確にしておく必要があります。
最初に要件定義でビジネス要件を整理して、データ項目を洗い出します。それをもとに、テーブル構造を設計していきます。
関係者にヒアリングなどを行ない、以下のような項目を確認します。
こうした情報を踏まえ、「このテーブルにはどのような列(フィールド)が必要か」「列の型はどれくらいのサイズが妥当か」などの構造を設計します。
テーブル設計のポイントは、最適な粒度でテーブルを切り分けることです。
例:
正規化 とは、リレーショナルデータベースで「データの重複や不整合を減らし、一貫性を高める」テーブル設計手法です。
正規化を行なうと、更新や削除が行ないやすくなり、データが破損するリスクを下げられます。またデータの検索や集計もわかりやすくなり、大規模なシステムであっても運用負荷を抑えられます。
よく使われる正規化の段階としては「第1正規形」「第2正規形」「第3正規形」などがあります。
リレーショナルデータベースでは、テーブル間の関係性を明確に定義することで、複数のデータを一貫性をもって扱うことができます。代表的な関係として、以下が挙げられます。
データ型の選定も、データベース設計において重要な要素です。
YYYY-MM-DD HH:MI:SS のように保存され、TIMESTAMPでは製品によって最大範囲が異なるケースもあります。インデックス は、テーブルに対して検索を高速化するための仕組みです。
よく使う列にインデックスを張っておけば、検索条件に合致する行を素早く探し出せます。一方で、インデックスが増えるとデータ更新時のオーバーヘッドが大きくなるため、どの列にインデックスを適用すべきかは慎重に決める必要があります。
多くのデータベースでは、インデックスに「B+木」や「ハッシュ」などのデータ構造を用いています。これにより、テーブルの全行を順番にスキャンするのではなく、インデックスを辿って必要な行だけを直接取得できるようになります。
例:
顧客 テーブルの 顧客ID にインデックスを張っておく顧客ID = 1003 のレコードを探すとき、インデックスを使うと直接その行を見つけられるもしインデックスがなければ、テーブルの全行に対して「顧客IDが1003かどうか」をチェックする必要があります。レコードが何百万件も存在するような大規模テーブルでは、インデックスを利用しないと検索速度が大幅に低下するおそれがあります。
インデックスをむやみに作りすぎると、INSERTやUPDATE、DELETEのたびにインデックス情報を更新しなければならないため、トランザクションの負荷が増えます。以下の点を考慮して、必要最小限のインデックスを設定します。
トランザクション とは、データベースにおける一連の処理をまとめた単位のことです。
トランザクションは、すべて成功するか、あるいはすべて失敗して元の状態に戻るかのどちらかにします。
たとえば1件の注文を登録する際、受注情報の追加と在庫数の更新をまとめて1つの「トランザクション」として扱います。トランザクションが途中で失敗した場合は、全体をロールバックし、データを一貫性のある状態に戻します。
データベースのトランザクション処理には、以下の ACID特性 が求められます。
同時実行制御 とは、複数のユーザーやアプリケーションが同時にトランザクションを実行しても、整合性を損なわないように制御する仕組みです。
代表的な方法として「ロック機構」があります。ロック機構 は、ある行やテーブルを更新中に、ほかのトランザクションが同じデータを読み書きしようとすると、どちらかを待機またはブロックする仕組みです。DBMSはこの排他制御を自動で行ない、コミットやロールバックのタイミングでロックを解放します。
トランザクション同士が同じリソースを使う場合のイメージ
予期せぬ障害によってサーバーがダウンしてしまった場合でも、データベースはログやバックアップを利用して復旧できるように設計されています。
このレッスンでは、データベースについて学びました。
リレーショナルデータベースの基本構造やSQLによるCRUD操作を体験することで、データを一元管理し、効率的に検索・更新・集計できる仕組みを理解しました。
また、テーブル間の関連づけや正規化、インデックスの活用を通して、データの重複や不整合を防ぎつつ高速アクセスを可能にする設計手法の重要性を確認しました。
データベースは、企業の業務システムやIT活用に必要不可欠です。ビジネスパーソンの業務知識を生かし、組織内でのデータ活用やデータ分析が行なえるようになりましょう。
このレッスンで学んだことを振り返り、理解度を確認しましょう。
下記の5つの質問に答えてください。「回答フォーマット」をコピーして、コメント欄に記入して提出してください。
回答フォーマット
1.
2.
3.
4.
5.