このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

データベース:: 具体例の記述方法

一連のデータベースに関する記事のハブ記事(リンク集がある記事)は「データベース:: テーブルのキーって何なのよ?」です。その他の記事はハブ記事からたどれます。

抽象的な議論だけでは分かりにくいので、データベースの具体例を入れたいのですが、具体例の記述がけっこう面倒です。現実的なデータベースでは複雑過ぎるので、オモチャの事例〈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}`$

とても大事な注意

前節のデータベースに関する記述を読んで、データベースの仕様をだいたい理解できると思います。「だいたい理解した気持ち」になったでしょう。-- それが問題なんです

もう一度、データベースのテーブル名と、各テーブルごとのカラム名とテーブルスキーマを列挙してみます。

  1. $`\n{S}\: \n{Gbfgs}\: ({\bf N}, {\bf Date} , {\bf String} , {\bf String} , {\bf Z})`$
  2. $`\n{T}\: \n{fglt}\: ({\bf String}, {\bf String}, {\bf String}, {\bf Z})`$
  3. $`\n{C}\: \n{nty}\: ({\bf String}, {\bf Z}, {\bf Year} )`$
  4. $`\n{CR}\: \n{csy}\: ({\bf String}, {\bf Z}, {\bf Year})`$
  5. $`\n{L}\: \n{cn}\: ({\bf Z}, {\bf String})`$
  6. $`\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が、自然言語由来の名前からの連想による判断をサポートする可能性はありますが。