9. データベース設計の実践
正規化の目的と手順、種々の正規形、
SQLを用いた正規化
1
金子邦彦
(データベース演習)
URL: https://www.kkaneko.jp/de/de/index.html
SQLスキルの向上
データベース運用スキル
問題解決能力と論理的思考力
2
9-1. イントロダクション
3
リレーショナルデータベースの仕組み
データをテーブルと呼ばれる表形式で保存
テーブル間関連で結ばれる。複雑な構造を持ったデータ
を効率的に管理することを可能に。
4
関連
正規化
目的
データベースの構造を最適化
効率的なデータベース管理を実現
方針
テーブルの数を減らすことよりも、データの冗長性(重複)
を減らすことを行う
5
正規化の例
6
正規化前 正規化後
名前
昼食
料金
A
そば
250
B
カレーライス
400
C
カレーライス
400
D
うどん
250
名前
昼食
A
そば
B
カレーライス
C
カレーライス
D
うどん
昼食
料金
そば
250
カレーライス
400
うどん
250
正規化により、元のテーブルにあった冗長性を排除
冗長なデータがある
冗長なデータがない
正規化のメリット
データの冗長性の減少 データの重複を減らす
異状の防止:更新、削除、挿入時の異状を防ぐ
効率の向上:データベース全体のサイズが縮小すると、ス
トレージの効率化とデータベース操作の高速化が期待でき
信頼性の確保:異状の防止により、データの信頼性の向上。
管理の容易化:データベースの管理が容易になる
7
名前
昼食
料金
A
そば
250
B
カレーライス
400
C
カレーライス
400
D
うどん
250
正規化前の問題
8
更新
350
カレーライスが
400円から 350円に値下げ
昼食の値段が1つのはずなのに、
350, 400 の違った値段の記録が
あり、不整合がある
400」をすべて「350」に変更
する必要があるが、変更を間
違ったとする
値段
400
250
名前
昼食
A
カレーライス
B
うどん
C
カレーライス
350
正規化による問題解消
9
更新 カレーライスが
400円から 350円に値下げ
400」をすべて「350」に変更
するのは1か所で済む。
間違いが起きにくい。
SQL を用いたデータベースの正規化
10
名前
昼食
料金
A
そば
250
B
カレーライス
400
C
カレーライス
400
D
うどん
250
名前
昼食
A
そば
B
カレーライス
C
カレーライス
D
うどん
昼食
料金
そば
250
カレーライス
400
うどん
250
正規化前
正規化後
CREATE TABLE X AS SELECT
DISTINCT 名前, 昼食 FROM T;
CREATE TABLE Y AS SELECT
DISTINCT 昼食, 料金 FROM T;
正規化と情報無損失
情報無損失の原則
正規化においては、元のデータベースの情報が失われたり
余計な情報が追加されたりしないことが重要
情報無損失の確認方法
正規化を施した後のテーブル群から、正規化する前のテー
ブルを正確に復元できるかどうかを検証
正規化が、データを損なわないことを保証
11
正規化と情報無損失
12
テーブル
テーブル テーブル
結合
正規化前
テーブル
正規化後
正規化後の
テーブル群を使い
正規化する前の
テーブル復元可能
正規化と情報無損失
13
名前
昼食
料金
A
そば
250
B
カレーライス
400
C
カレーライス
400
D
うどん
250
名前
昼食
A
そば
B
カレーライス
C
カレーライス
D
うどん
分割
昼食
料金
そば
250
カレーライス
400
うどん
250
情報無損失である:OK
データの冗長性が減少している:OK
テーブル名: X とする
テーブル名: Y とする
SELECT X.名前, X.昼食, Y.料金
FROM X JOIN Y ON X.昼食 = Y.昼食;
結合のコマンド
名前
昼食
料金
A
そば
250
B
カレーライス
400
C
カレーライス
400
D
うどん
250
このコマンドの実行により
元に戻る
商品テーブルと購入テーブル
14
関連
商品
ID
商品名
単価
1
みかん
50
2
りんご
100
3
メロン
500
購入者
商品番号
X
1
X
3
Y
2
購入
Xさんは、1みかんと,
3 メロンを買った
Yさんは、 2 りんごを買った
商品テーブルの情報
購入テーブルの情報
結合の例
商品テーブルと購入テーブルを
して、購入者がどの商品を購入
したかのデータを取得。
結合条件は、商品テーブルのID
性と購入テーブルの商品番号属性
が等しい場合に結合
15
関連
商品
ID
商品名
単価
1
みかん
50
2
りんご
100
3
メロン
500
購入者
商品番号
X
1
X
3
Y
2
購入
SELECT * FROM 商品
JOIN 購入
ON 商品.ID = 購入.商品番号;
ID 商品名 単価
購入者
商品番号
1
みかん
50
X
1
3
メロン
500
X
3
2
りんご
100
Y
2
結合の例
16
SQLの実行により
新しく生成される
テーブル
ID 商品名 単価
購入者
商品番号
1
みかん
50
X
1
3
メロン
500
X
3
2
りんご
100
Y
2
SELECT * FROM 商品
JOIN 購入
ON 商品.ID = 購入.商品番号;結合条件
結合のためのSQL
関連
商品
ID
商品名
単価
1
みかん
50
2
りんご
100
3
メロン
500
購入者
商品番号
X
1
X
3
Y
2
購入
結合条件の指定
商品テーブルの「ID」と購入テーブルの「商品番
号」属性が等しいという結合条件
等しい値を持つ」という結合条件の表し方
17
SELECT * FROM 商品
JOIN 購入
ON 商品.ID = 購入.商品番号;結合条件
結合のためのSQL
商品.ID = 購入.商品番号
テーブル1.属性3 = テーブル2.属性4
結合を行う SQL の例
SELECT 顧客.名前, 注文.注文日
FROM 顧客
JOIN 注文
ON 顧客.ID = 注文.顧客ID
WHERE 顧客.名前 = '山田' AND 注文.注文日 = '2023-11-03';
18
Access 固有の機能制限を気にしすぎるよりは、
次に示すような世界標準の書き方をマスターしましょう
問い合わせ結果からのテーブル生成
CREATE TABLE … AS
CREATE TABLE AS は、SQL SELECT文の結
に基づいて新しいテーブルを作成
19
名前
昼食
料金
A
そば
250
B
カレーライス
400
C
カレーライス
400
D
うどん
250
テーブル T
CREATE TABLE X AS
SELECT DISTINCT 名前, 昼食
FROM T;
昼食
料金
そば
250
カレーライス
400
うどん
250
テーブル X
Access 固有の機能制限を気にしすぎるよりは、
次に示すような世界標準の書き方をマスターしましょう
8-2. 演習
20
いまから演習で行うこと、注意点
次のテーブルを作成
Access での注意点】
SQLビューでは、SQL文を1つずつ実行
(複数まとめての一括実行ができない)
CREATE TABLE では、「実行」の後、画面が変化しない
が実行できている
INSERT INTO では、「実行」の後、確認表示が出る。そ
の後、画面が変化しないが実行できている 21
演習1.Access SQL
ビューを用いたテーブル定義
とデータの追加
【トピックス】
SQLビューを開く
SQL文の編集
create table
insert into
SQL文の実行
22
演習
1. パソコンを使用する
前もって Access をインストールしておくこと
2. Access 起動する
3. Access で、「空のデータベース」を選び、「作成」を
クリック.
23
4. テーブルツール画面が表示されることを確認
24
5. 次の手順で、SQLビューを開く.
25
②「デザイン」タブで、
表示」を展開し「SQL
ビュー」を選ぶ
①「作成」タブで、
クエリデザイン
をクリック
このような
表示が出た
ときは
閉じる」を
クリック
26
6. SQL ビューに、次の SQL を1つずつ入れ、「実行」ボタ
ンで、SQLを実行.結果を確認
CREATE TABLE T (
名前 TEXT,
昼食 TEXT,
料金 INTEGER);
INSERT INTO T VALUES('A', 'そば', 250);
INSERT INTO T VALUES('B', 'カレーライス', 400);
INSERT INTO T VALUES('C', 'カレーライス', 400);
INSERT INTO T VALUES('D', 'うどん', 250);
INSERT INTOでは、「実行」の後、確認
表示が出る。その後、画面が変化しない
が実行できている
間違ってしまったときは、テーブルの削除
を行ってからやり直した方が早い場合がある
27
テーブルビューで、削除した
いテーブルを右クリックして、
削除
テーブルを削除するときは、
間違って必要なテーブルを削除しない
ように、十分に注意する!
(元に戻せない)
演習2.種々のSQL問い合わ
せ. Access SQL ビューを
使用.
【トピックス】
1. 単純な表示
2. 特定の属性のみ表示(射影)
3. 重複行の除去 DISTINCT
28
Access SQL ビューを用いた問い合わせ
Access SQLビュー開く
SQL 編集select, from, where を使用
: select * from テーブル名 where 1 = 1;
SQL 実行
実行の結果、データシートビューに画面が変わり、そこに
い合わせの結果が表示される
さらにSQL 文の編集、実行を続ける場合には、画面を SQL
ビューに切り替える
29
30
SQL 問い合わせ(クエリ)で使用する2つのビュ
SQL ビュー
SQL 文の作成編集 データシートビュー
問い合わせ(クエリ)
結果
実行
表示 + SQL ビュー
マウス操作でビューを切り替え
1. 次の手順で、SQLビューを開く.
31
②「デザイン」タブで、
表示」を展開し「SQL
ビュー」を選ぶ
①「作成」タブで、
クエリデザイン
をクリック
このような
表示が出た
ときは
閉じる」を
クリック
32
2. SQL ビューに、次の SQL を1つずつ入れ、「
」ボタンで、SQLを実行.結果を確認
1. 単純な表示
SELECT * FROM T;
2. 昼食の列のみ
SELECT 昼食 FROM T;
33
(続き)
3.重複行の除去 DISTINCT
SELECT DISTINCT 昼食 FROM T;
演習3で行うこと
34
名前
昼食
料金
A
そば
250
B
カレーライス
400
C
カレーライス
400
D
うどん
250
名前
昼食
A
そば
B
カレーライス
C
カレーライス
D
うどん
分割
昼食
料金
そば
250
カレーライス
400
うどん
250
情報無損失である:OK
データの冗長性が減少している:OK
テーブル名: X とする
テーブル名: Y とする
名前
昼食
料金
A
そば
250
B
カレーライス
400
C
カレーライス
400
D
うどん
250
X Y の結合により元に戻る
演習3.正規化、正規化にお
ける情報無損失
【トピックス】
1. 問い合わせ結果によるテーブ
ル生成 INTO
2. 結合
3. 正規化
4. 正規化における情報無損失
35
1. 次の手順で、SQLビューを開く.
36
②「デザイン」タブで、
表示」を展開し「SQL
ビュー」を選ぶ
①「作成」タブで、
クエリデザイン
をクリック
このような
表示が出た
ときは
閉じる」を
クリック
37
2. SQL ビューに、次の SQL を1つずつ入れ、「
」ボタンで、SQLを実行.結果を確認
1. テーブル X の生成
SELECT DISTINCT 名前, 昼食 INTO X FROM T;
2. テーブル Y の生成
SELECT DISTINCT 昼食, 料金 INTO Y FROM T;
38
(続き)
3. テーブル X の確認
SELECT * FROM X;
4. テーブル Y の確認
SELECT * FROM Y;
39
(続き)
5.テーブルの結合により元に戻ることを確認
SELECT X.名前, X.昼食, Y.料金
FROM X INNER JOIN Y ON X.昼食 = Y.昼食;
リレーショナルデータベースのテーブルでは、行の順序は気にしない
ことになっている
自習1.SQLを用いた正規化
目的:次のテーブル S SQL を用いて正規化する
Access で次ページの SQL を1つずつ実行し、結果を確認
40
CREATE TABLE S (
StudentID INTEGER,
StudentName TEXT,
Course TEXT
);
INSERT INTO S VALUES (1, 'Alice', 'Math');
INSERT INTO S VALUES (1, 'Alice', 'Science');
INSERT INTO S VALUES (2, 'Bob', 'History');
INSERT INTO S VALUES (3, 'Charlie', 'Math');
INSERT INTO S VALUES (3, 'Charlie', 'History');
INSERT INTO S VALUES (3, 'Charlie', 'Science');
SELECT DISTINCT StudentID, StudentName INTO U FROM S;
SELECT DISTINCT StudentID, Course INTO V FROM S;
SELECT * FROM S;
SELECT * FROM U;
SELECT * FROM V;
SELECT U.StudentID, U.StudentName, V.Course
FROM U INNER JOIN V ON U.StudentID = V.StudentID; 41
42
SELECT * FROM S; の結果
SELECT * FROM U; の結果
43
SELECT * FROM V; の結果
SELECT U.StudentID, U.StudentName, V.Course
FROM U INNER JOIN V ON U.StudentID = V.StudentID;