理論から学ぶデータベース実践入門 ch1 SQLとリレーショナルモデル
まとめ
- SQLを使う以上、リレーショナルモデルから逃れることはできない
- リレーショナルモデルのリレーションとSQLのテーブルとの間にはさまざまな相違がある
- テーブルをリレーション(集合の一種)の性質に少しでも近づけることが重要
そもそもSQLって?
- リレーショナルデータベースに問い合わせを行う言語
- したがって、リレーショナルモデルがベースになっている
リレーショナルモデルを知らなくてもSQLは書ける?
- そういう人は多い
- が、新にスキルのあるDBエンジニアになるには必修
SQLとリレーショナルモデルって実はあんまり似てないよね?
RDBはリレーショナルモデルを正しく実践してこそ真価を発揮する!
- SQLはリレーショナルモデルをベースとしている
- ので、リレーショナルモデルに沿った演算が得意
- しかし柔軟さゆえ、リレーショナルモデルから逸脱した使い方もできてしまう
- いつの間にか非常に効率の悪いクエリばかり書くことに
- SQL文が複雑怪奇に
リレーショナルモデル
- データモデル
- データをどのように表現するか
- リレーショナルモデル
- データモデルの一種
- 他には、KVSとか
- データモデルの一種
- リレーション
- リレーショナルモデルにおける最重要概念
リレーションの定義
- ERD: Entity Relationship DiagramのRelationshipは関係ない
- Relationに相当するのはテーブルそのもの
- リレーションの構成要素
- 見出し(Heading)
- n個の属性の集合
- 属性(Attribute)
- 名前とデータ型とのペア
- 本体(Body)
- タプルの集合
- タプル(tuple)
- 属性値の集合
- 属性値は見出しで定義されたものと一致すること
- 見出し(Heading)
- リレーショナルモデルとSQLにおける各オブジェクトの対応
- ただし厳密に対応するものではない(後述)
リレーショナルモデル | SQL |
---|---|
リレーション | テーブル |
タプル | 行 |
属性 | カラム |
集合とリレーショナルモデル
- リレーションは集合の一種
- 集合の性質をもつ
- 集合(Set)
- ものの集まり
- 要素、元(Element)
- 集合に含まれる個々のもの
- 満たすべき要件
- 集合に含まれているかを不確定要素がなく判定できる
- unknownはダメ
- 重複してはいけない
- 含まれているか、いないかのみ
- 何個含まれているか、が演算結果に影響を及ぼしてはならない
- それ以上分割できない
- 集合に含まれているかを不確定要素がなく判定できる
- リレーショナルモデルとNULL
- NULLはunknownを表すマーカーなので集合には含められない
- よってリレーションにも含められない
- 有限集合と無限集合
- 異なる性質をもつもの
- コンピュータで表現する以上、有限集合のみ考えれば良い
リレーションの演算
- データと演算はセットになって初めて役に立つ
- 演算
- 制限(Restrict)
- 特定の条件に合うタプルのみ含んだリレーションを返す
- 元のリレーションの部分集合
- 射影(Projection)
- 特定の属性だけを含んだリレーションを返す
- タプルに重複が生ずることがある
- その場合、同一のタプルとみなされる
- 集合だから「何個含まれるか」は演算結果に影響しない
- その場合、同一のタプルとみなされる
- 拡張(Extend)
- 属性を増やす
- たいていderivative
- 属性を増やす
- 属性名変更(Rename)
- 和(Union)
- 2つのリレーションに含まれるすべてのタプルで構成されるリレーションを返す
- 重複は解消
- 積/交わり(Intersect)
- 2つのリレーションの共通部分になっているリレーションを返す
- 差(Difference)
- 2つのリレーションのうち一方のリレーションにのみ含まれるタプルから構成されるリレーションを返す
- 交換則成り立たない
- 直積(Product)
- 2つのリレーションのタプルをそれぞれ組み合わせたリレーションを返す
- 生成されたリレーションの見出しには2つのリレーションの見出しが持つ属性がすべて含まれる
- 結合(Join)
- 共通の属性を持つ2つのリレーションを、その共通の属性の値が同じタプル同士組み合わせたリレーションを返す
- 制限(Restrict)
- SQLの「外部結合」はリレーションの演算には含まれない
- 結果にNULLを含む可能性があるため
- 積、直積は結合の特殊なパターン
- 積: 属性がすべて共通
- 直積: 共通の属性が存在しない
コラム: 要素にNULLが含まれていると……
- NULLはリレーショナルモデルを根底から覆す不穏因子
- unknownが絡むため論理的に正しい答えは得られようもない
クロージャという性質
- リレーションの演算は閉包
- 数珠つなぎのように演算を記述できるため非常に重要
- リレーショナルモデルの真骨頂
リレーショナルモデルにおけるデータ型
SQLにおけるリレーション操作
- DMLとの対応関係
SELECTの基本形
FROM テーブルのリスト -- 直積 WHERE 検索条件 -- 制限 SELECT カラムのリスト -- 射影 ;
- RDBの中核たるSELECT文からして3つのリレーション演算からなる
- 論理的には上記の順番
- 実装上は最適化が行われ、変わるだろうが…
- 行の直積集合全部をフェッチするわけはない
- SELECT句の中で定義したエイリアス(拡張、属性名変更)をWHERE句で使えない理由
- 実装上は最適化が行われ、変わるだろうが…
INSERT(挿入)
- SQLにおけるテーブルは値と変数の両方の役割をもつ
- リレーションは値である
- 値そのものをmodifyするわけではない
a = a + 1;
- Relvar(Relation Variable, 関係変数)
- 値の入れ物
- INSERT:Relvarに格納されたリレーションを新しいリレーションに置き換える操作
- 新しいリレーション: 和集合
R := R ∪ {T}
DELETE(削除)
R := R - {T}
- 差集合
UPDATE(更新)
R := (R - {T}) ∪ {T2}
- WHERE句の条件に適合するリレーション
{T}
との差集合をとり - 修正を加えたリレーション
{T2}
との和集合をとる
SQLにあってリレーショナルモデルにないもの
- SQLをリレーショナルモデルに沿って使うためには封印する必要がある
要素の重複
- 制約がない場合、行が重複してもSQL上エラーにならない
- ここにおいて、テーブルはそもそも集合(Set)でない
- あえて言えばMultiset
- SetとMultisetの性質は異なる
- テーブルを集合と同じように使うには何らかの一意性制約が必要
要素間の順序
- SQLには順序が存在する
- カラム
- カラム位置
- 行
- ROWNUM関数、ORDER BY句
- カラム
リレーションの更新
- テーブルは値と変数の両方の機能を有し、mutable
- リレーションは値であり、immutable
トランザクション
ストアドプロシージャ
- 集合演算を真っ向から否定する行為
NULL
- Not Applicable / Unknown
- 値ではないため集合に含めることはできない
コラム: リレーショナルモデルは古典的か
- 重要なのは、リレーショナルモデルの限界を知ること
- リレーショナルモデルを適用できる部分と、そうでない部分とを見極めよ
- 適用可能な部分ではしっかりと実践せよ
- リレーショナルモデルの解釈自体を歪めるのはNG
- 例
- NULLの許容
- 属性やタプルに順序があるものと考える
- 数学的な正しさから乖離する
- 例
- 【所感】関数型プログラミングと似たものを感じる
- 完全に副作用を排すると目の前の箱が熱くなるだけ
- 純粋関数部分と副作用のある部分とを分けることが肝要