一連のデータベースに関する記事のハブ記事(リンク集がある記事)は「データベース:: テーブルのキーって何なのよ?」です。その他の記事はハブ記事からたどれます。
抽象的な議論だけでは分かりにくいので、データベースの具体例を入れたいのですが、具体例の記述がけっこう面倒です。現実的なデータベースでは複雑過ぎるので、オモチャの事例〈toy model〉にしますが、それでも面倒です。
この記事では、具体例の記述をできるだけ簡略にする方法と、その方法による具体例(の具体例)を挙げます。$`\newcommand{\n}[1]{\mathsf{#1}}
\newcommand{\bs}[1]{\boldsymbol{#1}}
\newcommand{\mrm}[1]{\mathrm{#1}}
`$
内容:
シリーズ・ハブ記事:
テーブル名とカラム名
次の規則を設けます。
- テーブル名は英字〈ラテン文字〉1文字から3文字までの名前とする。
- カラム名は英字1文字の名前とする。
とんでもない規則だと思うでしょうが、あくまでオモチャの事例の記述用です。さらに、名前の順番を仮定します。
- 名前は、文字列のソート順で順番付けられているとする。
これは、名前の集合にトータル順序〈total order | 全順序 | 線形順序〉が備わっているということです。
この規則のもとでは、カラム名の集合を単一の英字ワードで一意的に表現できます。例えば、カラム名の集合が $`\{\n{s}, \n{f}, \n{g}, \n{b},\n{G}\}`$ であったとき、対応する英字ワードは $`\n{Gbfgs}`$ です。英字ワードは、文字をアスキーコード順で並べます。アスキーコードでは、大文字が小文字より先です。
集合の記述にLaTeX(MathJax)を使っています。テーブル名としての文字は、イタリック体 $`b`$ ではなくてサンセリフ体 $`\n{b}`$ を使っています。イタリック体、ローマン体、サンセリフ体は、よく見れば区別できると思います。
[/注意]
短いテーブル名やカラム名は、もっと長い名前の短縮名だと考えます。例えば、カラム名の集合 $`\{\n{s}, \n{f}, \n{g}, \n{b}, \n{G}\}`$ は、架空の学校の学生に関するカラム名だとします。
日本語カラム名 | 英語カラム名 | 短縮名 |
---|---|---|
学生番号 | student id number | s |
姓 | family name | f |
名 | given name | g |
生年月日 | birth date | b |
学年 | school grade | G |
すべてのカラム名の集合は、英字ワード $`\n{Gbfgs}`$ で書けますが、部分集合は部分ワードで表現できます。例えば、$`\n{fg}`$ は姓と名の2カラムを表します。候補キーを示したいなら、「$`\n{s}`$ と $`\n{bfg}`$」と簡略に表現でき、候補キーの集合は $`\{\n{s}, \n{bfg}\}`$ と書けます。空集合は英字ワードで表現できないので、$`\emptyset`$ か $`\{\}`$ を使います。
カラム名の集合の部分集合に対する合併は、英字ワードを連接〈concatenate〉してから重複文字の除去と文字順をソートすればOKです。
$`\quad \n{Gs} \cup \n{Gfg} \\
\leadsto \n{GsGfg}\\
\leadsto \n{Gsfg}\\
\leadsto \n{Gfgs}\\
\text{したがって、}\\
\quad \n{Gs} \cup \n{Gfg} = \n{Gfgs}
`$
テーブルスキーマとタプル
「データベース:: テーブル構造とデータベース構造」で述べたように、データベースにはテーブル名の集合 $`I`$ があります。$`i\in I`$ に対して、テーブル構造とその構成素が対応しています。それを、もう一度繰り返し書くと:
$`\text{For } (I \ni i \mapsto \bs{t}_i) \\
\quad C_i := \mrm{Column}(\bs{t}_i ) \\
\quad S_i := \mrm{Schema}(\bs{t}_i ) \\
\quad \Gamma_i := \mrm{Class}(\bs{t}_i )
`$
具体例として、次のようなテーブル名の集合を考えます。
$`\quad I= \{\n{S}, \n{T}, \n{C}, \n{CR}, \n{L}, \n{LC}\}`$
テーブル名は次の長い名前の短縮名です。
日本語テーブル名 | 英語テーブル名 | 短縮名 |
---|---|---|
学生 | student | S |
教員 | teacher | T |
科目 | course | C |
履修登録 | course registration | CR |
研究室 | laboratory | L |
研究室登録 | laboratory registration | LR |
テーブルスキーマを記述するにはドメイン〈ASPDT | Application Specific Primitive Data-Type〉が必要です。次のデータ型は使っていいとします。
- $`{\bf N}`$ : 自然数型
- $`{\bf Z}`$ : 整数型
- $`{\bf B}`$ : ブーリアン〈真偽値〉型
- $`{\bf String}`$ : 文字列型
- $`{\bf Date}`$ : 日付型
- $`{\bf Year}`$ : 年型(日付の年だけの型)
具体的なテーブル名 $`\n{S} \in I`$ に対して、そのテーブルスキーマは次のように書きます。
$`\quad C_{\n{S}} := \n{Gbfgs} = \{\n{s}, \n{f}, \n{g}, \n{b}, \n{G}\}\\
\quad S_{\n{S}} := (\n{G}:{\bf N}, \n{b}:{\bf Date} ,\n{f}:{\bf String} ,\n{g}:{\bf String} ,\n{s}: {\bf Z})
`$
「学年の値はもっと制限できるだろう」とか「学生番号に負の値は使わんだろう」とかツッコミどころはあるでしょうが、そこはいいとします(とりあえず決めることが大事)。
テーブルスキーマにおける各項目(型宣言)は、必ずカラム名の順番に書くと約束すれば、次のように簡略化できます。
$`\quad C_{\n{S}} := \n{Gbfgs}\\
\quad S_{\n{S}} := ({\bf N}, {\bf Date} , {\bf String} , {\bf String} , {\bf Z})
`$
個々のタプルも、順番を守って記述すれば、カラム名は不要になります。例えば:
$`\quad (2, \text{2004-08-29}, \text{"鈴木"}, \text{"一郎"}, 222397)`$
テーブル名の集合 $`\{\n{S}, \n{T}, \n{C}, \n{CR}, \n{L}, \n{LR}\}`$ のすべての名前($`\n{S}`$ も含めて)に対するテーブルスキーマ/候補キー/外部キーを列挙しておきます。外部キーはまだ説明してませんが、カラム名の部分集合と参照先テーブル名を書いておきます。
テーブル S
学生:
日本語カラム名 | 英語カラム名 | 短縮名 |
---|---|---|
学生番号 | student id number | s |
姓 | family name | f |
名 | given name | g |
生年月日 | birth date | b |
学年 | school grade | G |
$`\quad C_{\n{S}} := \n{Gbfgs}\\
\quad S_{\n{S}} := ({\bf N}, {\bf Date} , {\bf String} , {\bf String} , {\bf Z})
`$
候補キー: $`\n{G}, \n{fgb}`$
テーブル T
教員:
日本語カラム名 | 英語カラム名 | 短縮名 |
---|---|---|
教員番号 | teacher id number | t |
姓 | family name | f |
名 | given name | g |
所属研究室 | laboratory | l |
$`\quad C_{\n{T}} := \n{fglt}\\
\quad S_{\n{T}} := ({\bf String}, {\bf String}, {\bf String}, {\bf Z})
`$
候補キー: $`\n{fg}, \n{t}`$
外部キー | 参照先テーブル |
---|---|
$`\n{l}`$ | $`\n{L}`$ |
テーブル C
科目:
日本語カラム名 | 英語カラム名 | 短縮名 |
---|---|---|
科目名 | course name | n |
年度 | year | y |
担当 | teacher | t |
$`\quad C_{\n{C}} := \n{nty}\\
\quad S_{\n{C}} := ({\bf String}, {\bf Z}, {\bf Year} )
`$
候補キー: $`\n{ny}`$
外部キー | 参照先テーブル |
---|---|
$`\n{t}`$ | $`\n{T}`$ |
テーブル CR
履修登録:
日本語カラム名 | 英語カラム名 | 短縮名 |
---|---|---|
学生 | student | s |
科目 | course | c |
年度 | year | y |
$`\quad C_{\n{CR}} := \n{csy}\\
\quad S_{\n{CR}} := ({\bf String}, {\bf Z}, {\bf Year})
`$
候補キー: $`\n{csy}`$
外部キー | 参照先テーブル |
---|---|
$`\n{s}`$ | $`\n{S}`$ |
$`\n{cy}`$ | $`\n{C}`$ |
テーブル L
研究室:
日本語カラム名 | 英語カラム名 | 短縮名 |
---|---|---|
名前 | name | n |
主任 | cheaf | c |
$`\quad C_{\n{L}} := \n{cn}\\
\quad S_{\n{L}} := ({\bf Z}, {\bf String})
`$
候補キー: $`\n{n}`$
外部キー | 参照先テーブル |
---|---|
$`\n{c}`$ | $`\n{T}`$ |
テーブル LR
研究室登録:
日本語カラム名 | 英語カラム名 | 短縮名 |
---|---|---|
学生 | student | s |
研究室 | laboratory | l |
$`\quad C_{\n{LR}} := \n{ls}\\
\quad S_{\n{LR}} := ({\bf String}, {\bf Z})
`$
候補キー: $`\n{ls}`$
外部キー | 参照先テーブル |
---|---|
$`\n{s}`$ | $`\n{S}`$ |
$`\n{l}`$ | $`\n{L}`$ |
とても大事な注意
前節のデータベースに関する記述を読んで、データベースの仕様をだいたい理解できると思います。「だいたい理解した気持ち」になったでしょう。-- それが問題なんです。
もう一度、データベースのテーブル名と、各テーブルごとのカラム名とテーブルスキーマを列挙してみます。
- $`\n{S}\: \n{Gbfgs}\: ({\bf N}, {\bf Date} , {\bf String} , {\bf String} , {\bf Z})`$
- $`\n{T}\: \n{fglt}\: ({\bf String}, {\bf String}, {\bf String}, {\bf Z})`$
- $`\n{C}\: \n{nty}\: ({\bf String}, {\bf Z}, {\bf Year} )`$
- $`\n{CR}\: \n{csy}\: ({\bf String}, {\bf Z}, {\bf Year})`$
- $`\n{L}\: \n{cn}\: ({\bf Z}, {\bf String})`$
- $`\n{LR}\: \n{ls}\: ({\bf String}, {\bf Z})`$
候補キーと外部キーの情報もありますから、それらの情報も入れたとして、「だいたい理解した気持ち」は、今列挙した形式的な記述〈formal description〉からもたらされていますか?
冷静に考えてみると、そうではないですよね。長いほうのテーブル名/カラム名、「履修登録」とか「学生番号」とかにより「だいたい理解した気持ち」が形成されたはずです。逆に言うと、長い名前がなかったら、「なんだかサッパリ分からない気持ち」でしょう。
先に出した1個のタプルを再掲します。
$`\quad C_{\n{S}} := \n{Gbfgs}\\
\quad S_{\n{S}} := ({\bf N}, {\bf Date} , {\bf String} , {\bf String} , {\bf Z})\\
\:\\
\quad (2, \text{2004-08-29}, \text{"鈴木"}, \text{"一郎"}, 222397)
`$
このタプルは特に問題ないでしょう。では、少し変更した次のタプルはどうでしょう。
$`\quad (29, \text{2004-08-29}, \text{"鈴木"}, \text{"-?a ☆!!"}, 222397)
`$
「このタプルはオカシイだろう」と思いますよね。しかし、テーブルスキーマと照合してオカシイ(非妥当)なところは何もありません。
$`\quad (29, \text{2004-08-29}, \text{"鈴木"}, \text{"-?a ☆!!"}, 222397) \in \mrm{Tuple}(S_{\n{S}})
`$
オカシイと判断した理由は、「学生の学年が29年生ってありえん」、「人の名前に $`\text{"-?a ☆!!"}`$ なんて文字列は使えない」、ですよね。これは常識を利用しています。データベース/テーブルの定義として明示的に書いてあるわけではないです。
テーブル名/カラム名に、自然言語由来の説明的な長い名前を使う、あるいは注釈的に長い名前を添えるのは、その名前からテーブル/カラムのセマンティクス〈意味論〉を連想させるためです。暗示されたセマンティクスを基準に、タプルやテーブルインスタンス(タプルの集合)の妥当/非妥当を判断させるためです。
しかし、自然言語由来の名前からの連想による判断は、客観性・確実性がありません。コンピュータにアルゴリズム的に判断させるときには使えません*1。
テーブルクラス(「データベース:: テーブルのキーって何なのよ?」参照)という概念は、暗示と連想に変わる判断基準です。数理モデルとしての理想化・抽象化をしてますが、与えられたテーブルインスタンス $`T`$ が妥当であることは、テーブルクラスに所属すること $`T \in \Gamma`$ で記述できます。
$`T \in \Gamma`$ は、人間が真偽決定可能な命題だとは思えませんが、集合論的命題ってそんなものです。全知全能の神様でないと真偽決定できないとしても、それでも真偽決定可能だとみなします。
テーブルクラスを含んだテーブル構造、さらにはデータベースクラス(「データベース:: テーブル構造とデータベース構造」参照)を含んだデータベース構造を想定するのは、曖昧で不確実な暗示と連想に頼った記述・定義から抜け出したいからです。
*1:AIが、自然言語由来の名前からの連想による判断をサポートする可能性はありますが。