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

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

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

参照用 記事

データベース:: テーブルのキーって何なのよ?

2019年に「データベース:: 論理の使い所は」という記事を書きました。タイトルに「データベース::」という接頭辞を付けたのは、一連の記事を検索しやすくするためです。一連の記事とは、次の意図で書かれる“はずだった”記事です。

ちゃんと書こうと思うと億劫になるので、ふと思い立ったときに、データベースと論理に関するラフなメモ書きを残すことにします。

ところが、接頭辞「データベース::」が付いた記事は2019年の記事一本だけ。続きはありませんでした。

最近(2023年6月)、「カーディナリティ〈多重度〉の“カラスの足”記法が分からない」という記事を書きました。この記事を書いた後で、「データベースに関連する記事になんか接頭辞を付ける気でいたような?」と思い出しました。“カラスの足”記事のタイトルを変える気はありませんが、この記事には接頭辞「データベース::」を付けました。4年ぶりの2本目の記事となります。

この記事の話題は、よく知られた“テーブルのキー”についてです。「よく知られた」と書きましたが、それほどよく知られてないんじゃないのかなぁ、という思いが記事を書いた動機です。$`\require{color}
\newcommand{\Keyword}[1]{ \textcolor{green}{\text{#1}} }
\newcommand{\For}{\Keyword{For }}
\newcommand{\Define}{\Keyword{Define }}
\newcommand{\Imp}{ \Rightarrow }
\newcommand{\mrm}[1]{\mathrm{#1}}
\newcommand{\hyp}{\text{-}}
\newcommand{\Iff}{\Leftrightarrow}
\newcommand{\Doms}{\mathscr{D}}
`$

内容:

シリーズ記事:

  1. データベース:: 論理の使い所は
  2. データベース:: テーブルのキーって何なのよ? (この記事)
  3. データベース:: テーブル構造とデータベース構造
  4. データベース:: 具体例の記述方法
  5. データベース:: テーブル間の参照
  6. データベース:: 記法と用語のまとめ

関連記事

  1. データベース・テーブルの変更を圏論的に見るならば
  2. 関係(非決定性写像)に関する用語
  3. (続き) 関係(非決定性写像)に関する記法
  4. テンソル計算(の準備)と型推論・エラボレーション
  5. カーディナリティ〈多重度〉の“カラスの足”記法が分からない
  6. 続報・カーディナリティ(多項関係、関係の属性も)

カラム、ドメイン、テーブルスキーマ

データベース:: 論理の使い所は」にて:

数学における(標準的な)関係概念はきわめてクリアです。が、RDBの世界の「関係〈リレーション〉」はそれとは別の意味で使われています。ここでは、「関係」は数学の標準的な意味で使い、RDBジャーゴン(RDBコミュニティ特有の隠語)としての「関係」は「テーブル」と呼びます。

というわけで、「関係」「属性」は後で使うために温存しておき、「テーブル」「カラム」を使います。例えば、通常「関係スキーマ〈リレーションスキーマ〉」と呼ばれるものを「テーブルスキーマ」と呼びます。

カラムに関して、カラム名とカラム関数(後述)を区別します。カラム名とは何かというと、カラム名の集合の要素です。カラム名の集合は単なる有限集合です。

  • カラム名の集合〈set of column names〉とは、(任意の)有限集合のこと。空集合も認めます。
  • カラム名〈column name〉とは、カラム名の集合の要素のこと。

「これでは何も定義してないではないか」と思うでしょう、そのとおりです! カラム名が実体として何であるかは一切定義しません。「とある有限集合の要素」以上の意味はありません。

同様に、ドメインも実体として何であるかは定義しないで、呼び名だけ決めます。

  • ドメインの集合〈set of domains〉とは、集合を要素とする有限集合のこと。
  • ドメイン〈domain〉とは、ドメインの集合の要素のこと。

“ドメインの集合”が“集合の集合”なので、ドメインは集合です。ドメインの集合に属するドメイン(と呼ばれる集合)は、基本データ型〈primitive data-type〉だと思ってください。整数型、文字列型、真偽値型のような汎用・共通な基本データ型だけでなくて、特定の応用状況で使う基本データ型、例えば、身長型、年齢型、性別型、製品番号型、都道府県コード型とかでもいいです。

「ドメイン」という言葉は、他の意味でも使われていてコンフリクトするので、混乱を招きそうなときは「ドメイン〈ASPDT〉」と書くことにします。ASPDT は、Application Specific Primitive Data-Type のことです。Application Specific も Domain Specific としたかったのですが、さっそくに Domain がコンフリクトしました(苦笑)。

ドメイン〈ASPDT〉の集合(有限個の基本データ型の集まり)は前もって決められているとして、それを $`\Doms`$ とします。

テーブルスキーマ〈table schema〉とは、カラム名の集合 $`C`$ から、ドメイン〈ASPDT〉の集合 $`\Doms`$ への写像〈関数〉です。つまり、

$`\quad S : C \to \Doms`$ (写像)

$`C`$ は有限集合なので、$`C = \{c_1, \cdots, c_n \}`$ と書けます。$`S(c_i) = D_i`$ として、次のように書くことにします。

$`\quad S = (c_1 : D_1, \cdots, c_n: D_n )`$

特に、$`C`$ が番号の集合 $`C = \{1, \cdots, n \}`$ のときは、次のように略記します。

$`\quad S = (D_1, \cdots, D_n)`$

この場合、テーブルスキーマは単にドメイン〈APSTD〉のリストになります。同じドメインが何度も出現してもかまいません。

カラム名の集合が空集合のときも、テーブルスキーマはひとつ存在します。それは次のように書けます。

$`\quad S = ()`$ (ドメインの空リスト)

カラム名の集合が空集合である(唯一の)テーブルスキーマを空テーブルスキーマ〈empty table schema〉と呼びます。空テーブルスキーマは無意味なわけではなく、必要なものです。

個々のカラム名が何であるかは、今の文脈では重要ではないので、主に $`C = \{1, \cdots, n \}`$ のケースを考えます。具体例のときは、カラム名で現実的意味を示唆することが多いので、自然言語由来のカラム名を用います。例えば:

$`\quad S = (\text{姓}: {\bf String}, \text{名}: {\bf String}, \text{生年月日}: {\bf Date})`$

タプルとテーブルインスタンス

$`S:C \to \Doms`$ をテーブルスキーマとします。$`S`$ のタプルは、カラム名に値を割り当てる関数 $`t`$ のことです。ただし、次の条件を満たす必要があります。

  • $`c\in C`$ に対して、$`t(c) \in S(c)`$ である。

習慣により、$`t(c)`$ は $`t_c`$ とも書かれます。$`C = \{1, \cdots, n\}`$ のときなら、$`t(i) = t_i`$ であり、$`t = (t_1, \cdots, t_n)`$ とお馴染みの形で書けます。

テーブルスキーマ $`S`$ のタプル全体からなる集合を $`\mrm{Tuple}(S)`$ とします。$`C = \{1, \cdots, n\}`$ で $`S = (D_1, \cdots, D_n)`$ のときは、次のように書けます。

$`\quad \mrm{Tuple}(S) \cong D_1 \times \cdots\times D_n`$

記号 '$`\cong`$' は集合の同型の意味ですが、左右を同一視してイコールだと思ってもかまいません。

[補足]
シグマ型とパイ型を知っているなら、$`\mrm{Tuple}(S)`$ は次のように記述できます。

$`\quad \mrm{Tuple}(S) := \prod_{c\in C} S(c)\\
= \mrm{Sect}(\pi : \sum_{c\in C} S(c) \to C)
`$

ここで、$`\pi`$ はシグマ型にともなう射影で、$`\mrm{Sect}(\hyp)`$ は射影のセクションの集合を表します。次のように書けます。

$`\quad t \in \mrm{Tuple}(S)\\
\Iff t \in \mrm{Map}(C, \sum_{c\in C} S(c)) \land \pi\circ t = \mrm{id}_C`$
[/補足]

テーブルスキーマ $`S`$ のタプルを関数とみなした場合の余域〈codomain〉は $`\bigcup S`$ と書くことにします。$`S = (D_1, \cdots, D_n)`$ のときなら、次のように書けます。

$`\quad \bigcup S \\
= \bigcup (D_1, \cdots, D_n)\\
= D_1\cup \cdots\cup D_n
`$

シグマ型を知っているなら、$`\bigcup S`$ の代わりにシグマ型 $`\sum S = \sum_{c\in C} S(c)`$ で考えてもいいです。

タプルの集合 $`\mrm{Tuple}(S)`$ の部分集合を、テーブルスキーマ $`S`$ のテーブルインスタンス〈table instance〉と呼びます。つまり、

$`\quad T \text{ は } S \text{ のテーブルインスタンス}\\
\Iff T \subseteq \mrm{Tuple}(S)
`$

テーブルスキーマ $`S`$ のすべてのテーブルインスタンスからなる集合は $`\mrm{Pow}(\mrm{Tuple}(S))`$ と書けます。ここで、$`\mrm{Pow}(\hyp)`$ はベキ集合〈powerset〉です。

カラム名の集合と射影関数

関係データベースにおいて、「キー」は重要な概念だと思いますが、その「キー」に関してハッキリとした定義はされてないことが多いようです。とあるデータベース教材から超キー〈superkey〉の定義を引用します。

与えられたテーブルスキーマ $`S`$ のいかなるテーブルインスタンスにおいても、二つ以上のタプルが同一とならないようなカラム名の集合

「二つ以上のタプルが同一とならない」の意味がちょっと分かりにくいので、ハッキリさせましょう。

カラム名の集合 $`C`$ の部分集合を $`X, Y`$ などで表します。$`X\subseteq C`$ があると、テーブルスキーマ $`S:C \to \Doms`$ を $`X`$ に制限できます。例えば、$`C = \{a, b, c\}, X = \{a, c\}`$ ならば、$`X`$ に制限された $`S`$ は次のように書けます。

$`\quad (a: S(a), c:S(c))`$

$`X`$ に制限された $`S`$ は $`S|_X`$ と書きます。

$`\quad S = (a:S(a), b:S(b), c:S(c))\\
\quad S|_X = (a: S(a), c:S(c))`$

$`S|_X`$ もテーブルスキーマなので、タプルの集合 $`\mrm{Tuple}(S|_X)`$ を考えることができます。$`\mrm{Tuple}(S)`$ の要素($`S`$ のタプル)から、$`\mrm{Tuple}(S|_X)`$ の要素($`S|_X`$ のタプル)を自然に作ることができます。それは、次のような写像〈関数〉があるということです。

$`\quad \pi_X : \mrm{Tuple}(S) \to \mrm{Tuple}(S|_X)`$

タプル $`t \in \mrm{Tuple}(S)`$ は、$`t:C \to \bigcup S`$ という関数でした。関数としての $`t`$ を $`X`$ に制限することができます。域が $`X`$ に制限された $`t`$ を $`\pi_X(t)`$ と書くのです。例えば、先の例で、$`t = (t_a, t_b, t_c)`$ が $`S`$ のタプルのとき $`\pi_X(t)`$ は $`(t_a, t_c)`$ です。この $`\pi_X`$ を、部分集合 $`X \subseteq C`$ が決める射影関数〈projection function〉と呼びます。

特に、$`c\in C`$ として、単元集合 $`\{c\}`$ が決める射影関数は次の形です。

$`\quad \pi_{ \{c\}} : \mrm{Tuple}(S) \to \mrm{Tuple}(S|_{\{c\}})`$

$`\mrm{Tuple}(S|_{\{c\}})`$ と $`S(c)`$ は標準的に〈canonically〉同型なので、次の図式を可換にする写像 $`\pi_c`$ が決まります。

$`\require{AMScd}
\begin{CD}
\mrm{Tuple}(S) @>{\pi_{ \{c\}}}>> \mrm{Tuple}(S|_{\{c\}}) \\
@| @VV{\cong}V\\
\mrm{Tuple}(S) @>{\pi_c }>> S(c)
\end{CD}
`$

こうして決まる写像 $`\pi_c : \mrm{Tuple}(S) \to S(c)`$ をカラム関数〈column function〉と呼ぶことにします。カラム関数は、タプルの特定成分の値(関数とみなしたタプルの、特定引数に対する戻り値)を取り出す関数です*1

$`\mrm{Tuple}(S|_X)`$ は頻繁に使うので、$`X`$ を(小さな下付きではなくて)大きくして $`\mrm{Tuple}(S, X)`$ とも書きます。$`\mrm{Tuple}(S) = \mrm{Tuple}(S, C)`$ です。

さて、先の「二つ以上のタプルが同一とならない」ですが、カラム名の集合の部分集合を $`X \subseteq C`$ として、

  • 二つ以上のタプルの、射影関数 $`\pi_X`$ による値が同一とならない

の意味です。ここで、「二つ以上のタプル」は、テーブルインスタンス $`T`$ の要素だとします。つまり、

  • テーブルインスタンス $`T`$ の要素である二つ以上のタプルの、射影関数 $`\pi_X`$ による値が同一とならない

これを論理式で表現すれば、次のようです。

$`\quad \lnot \exists t, t' \in T.\, t \ne t' \land \pi_X(t) = \pi_X(t')`$

日本語に逐語翻訳するなら:

$`t`$ と $`t'`$ は異なっていて ($`t \ne t'`$)
かつ ($`\land`$)
射影関数による値は同一 ($`\pi_X(t) = \pi_X(t')`$)
であるようなテーブルインスタンス $`T`$ の要素 $`t, t'`$ が存在する ($`\exists t, t' \in T.`$)
ことはない ($`\lnot`$)

これで、「二つ以上のタプルが同一とならない」の意味がハッキリしました。

[補足]
$`S:C \to \Doms`$ がテーブルスキーマで、$`t\in \mrm{Tuple}(S)`$ が $`S`$ のタプルのとき、$`X \subseteq C`$ に対する射影 $`\pi_X`$ による値 $`\pi_X(t)`$ を $`t[X]`$ と書く習慣があるようです。値だけでなくて、テーブルインスタンス $`T\subseteq \mrm{Tuple}(S)`$ に対する像集合 $`\pi_X(T)`$ にも $`T[X]`$ という記法を使います。ブラケットを、次の2つの意味でオーバーロードしているわけです。

$`\quad (\hyp)[X] : \mrm{Tuple}(S, C) \to \mrm{Tuple}(S, X) \\
\quad (\hyp)[X] : \mrm{Pow}(\mrm{Tuple}(S, C)) \to \mrm{Pow}(\mrm{Tuple}(S, X))
`$

この記事内ではブラケット記法を使いませんが、データベース理論ではブラケット記法をよく見かけます。
[/補足]

自明なキー以外のキーは存在しない

超キーの定義を再掲します。

与えられたテーブルスキーマ $`S`$ のいかなるテーブルインスタンスにおいても、二つ以上のタプルが同一とならないようなカラム名の集合

$`S:C \to \Doms`$ が与えられたテーブルスキーマだとして、カラム名の集合 $`X \subseteq C`$ が超キーである条件は次のようです。

$`\quad \forall T \in \mrm{Pow}(\mrm{Tuple}(S)).\\
\qquad \lnot \exists t, t' \in T.\, t \ne t' \land \pi_X(t) = \pi_X(t')
`$

$`\forall T \in \mrm{Pow}(\mrm{Tuple}(S)).`$ が「いかなるテーブルインスタンスにおいても」に相当します。$`\forall T \in \mrm{Pow}(\mrm{Tuple}(S)).`$ を逐語翻訳するならば:

テーブルスキーマ $`S`$ のタプルの集合 ($`\mrm{Tuple}(S)`$)
の任意の ($`\forall`$) 部分集合 $`T`$ ($`T \in \mrm{Pow}(\mrm{Tuple}(S))`$)
に対して

$`X = C`$ ならばこの条件は満たされます。つまり、カラム名の集合 $`C`$ はテーブルスキーマ $`S`$ の超キーです。この場合は当たり前なので、$`C`$ を自明な超キー〈trivial superkey〉と呼びます。

では、自明でない超キーは存在するでしょうか? 超キーの定義を文字通りに受け取ると、自明でない超キーは存在しません

テーブルスキーマ $`S:C \to \Doms`$ に次の仮定を設けます。この仮定が特殊な条件だと思う人はいないでしょう。

  1. カラム名の集合 $`C`$ は空集合ではない。
  2. 任意のカラム名 $`c\in C`$ に対して、ドメイン〈ASPDT〉$`S(c)`$ は2個以上の要素を持つ。

この仮定のもとで、部分集合 $`X\subseteq C`$ が $`X \ne C`$ ならば、超キーになれないことを示しましょう。

$`C \ne \emptyset \land X \ne C`$ なので、$`a\in C \land a \not\in X`$ であるカラム名 $`a`$ を取れます。仮定より $`S(a)`$ は2個以上の要素を持つので、異なる2つの要素〈値〉を $`v, v' \in S(a)`$ とします。

タプル $`s\in \mrm{Tuple}(S)`$ をひとつ選びます(何でもいいです)。$`s`$ から2つのタプル $`t, t'\in \mrm{Tuple}(S)`$ を次のように作ります。

  • $`t_a = v`$ 、 $`a`$ 以外の $`c\in C`$ に対しては $`t_c = s_c`$
  • $`t'_a = v'`$ 、 $`a`$ 以外の $`c\in C`$ に対しては $`t'_c = s_c`$

こうして作った $`t, t'`$ は次の条件を満たします。

  • $`t \ne t'`$ (カラム名 $`a`$ での値 $`v, v'`$ が違うから)
  • $`\pi_X(t) = \pi_X(t')`$ ($`a`$ 以外のカラム名での値は同じだから)

テーブルインスタンス $`T \subseteq \mrm{Tuple}(S)`$ を次のように定義します。

$`\quad T := \{t, t'\}`$

この $`T`$ については、次の命題が成立します*2

$`\quad \exists t, t' \in T.\, t \ne t' \land \pi_X(t) = \pi_X(t')`$

よって、$`X`$ は超キーの条件を満たしません。$`X \ne C`$ であるかぎり、超キーにはなれないのです。

非自明な超キーが存在しないと、非自明な候補キー〈candidate key〉も存在しないし、非自明な主キー〈primary key〉も存在しません。

「そんなバカな」と思うでしょ。そう、なんかオカシイのです。超キーの定義がオカシイのですよ。

テーブルクラス

超キーの定義の「いかなるテーブルインスタンスにおいても」の「いかなる」が問題なのです。前節で、「いかなる」を $`\forall T \in \mrm{Pow}(\mrm{Tuple}(S)).`$ と解釈したのですが、そうではないのです。テーブルインスタンスの集合 $`\Gamma`$ が事前に決まっていて、$`\Gamma`$ に相対的に超キーが定義されるのです。

$`S:C \to \Doms`$ はテーブルスキーマとして、$`\Gamma \subseteq \mrm{Pow}(\mrm{Tuple}(S))`$ も与えられているとします。そのとき、$`X \subseteq C`$ が、$`\Gamma`$ に対して超キー〈superkey〉であるとは次のことです。

$`\quad \forall T \in \Gamma.\\
\qquad \lnot \exists t, t' \in T.\, t \ne t' \land \pi_X(t) = \pi_X(t')
`$

$`\Gamma \subseteq \mrm{Pow}(\mrm{Tuple}(S))`$ を、$`S`$ のテーブルクラス〈table class〉と呼ぶことにします。「クラス」という言葉も多用され過ぎてワケワカラナイのですが、「インスタンスの集まり」というなら「クラス」しかない気もします。

もう一度確認すると、超キーという概念は、テーブルスキーマに対して決まるのではなくて、テーブルスキーマのテーブルクラスを指定して初めて決まる概念です。テーブルクラスが不明だと、超キーかどうかの判断が出来ません。すべてのテーブルインスタンスからなるテーブルクラス(最大のテーブルクラス)に対しては、自明な超キーしか存在しません(前節の話)。

通常、テーブルクラス(に相当する概念)に言及されないのは、テーブルスキーマに付けられた自然言語由来の名前、例えば「社員」「製品」「学生」などから、対応するテーブルクラスを暗黙に連想させる方法が採られているからでしょう*3。しかし、暗黙の連想に頼ったコミュニケーションって碌なことにならないんだよね。

あらためてキーの定義

仕切り直しをしましょう。キー概念、つまり超キー、候補キー、主キーをちゃんと定義しましょう。

まず、ドメインの集合 $`\Doms`$ は決まっているとします。ドメイン設計は済んでいる、とも言えます。固定された $`\Doms`$ のもとでさらに $`C, S`$ を決めます。

  • $`C`$ は、カラム名の集合である。有限集合なら何でもいい。
  • $`S`$ は、$`S:C \to \Doms`$ という写像である。
  • $`S`$ が決まれば、$`C`$ は“写像 $`S`$ の域〈domain〉” と位置づけられる。(「ドメイン〈domain〉」がまたコンフリクト。)

$`S`$ が決まると、$`S`$ のテーブルインスタンスという概念を定義できます。

  • $`T`$ が $`S`$ のテーブルインスタンス ⇔ $`T\subseteq \mrm{Tuple}(S)`$
  • 同じことだが、$`T\in \mrm{Pow}(\mrm{Tuple}(S))`$

そして、前節で述べたテーブルクラス $`\Gamma`$ を、暗黙でなくて明示的に決めます。

  • $`\Gamma`$ はテーブルインスタンスの集合である。
  • 同じことだが、$`\Gamma \subseteq \mrm{Pow}(\mrm{Tuple}(S))`$
  • 同じことだが、$`\Gamma \in \mrm{Pow}( \mrm{Pow}(\mrm{Tuple}(S)) )`$

ここまでに出てきたすべての構成素〈constituent〉達を並べてまとめると:

$`\quad (\Doms, C, S, \Gamma)`$

これらで決まる構造をテーブル構造〈table structure〉と呼ぶことにしましょう。特定のテーブルクラス $`\Gamma`$ も含めるところがミソです。

$`\Doms`$ は文脈内に固定されているとして省略し、以下のような表現を使うことにします。

  • カラム名の集合 $`C`$
  • $`C`$ 上のテーブルスキーマ $`S`$
  • テーブルスキーマ $`(C, S)`$
  • テーブルスキーマ $`S`$ ($`C = \mrm{dom}(S)`$ として再現できるので、$`C`$ を省略している)
  • $`(C, S)`$ 上のテーブルクラス $`\Gamma`$
  • テーブル構造 $`(C, S, \Gamma)`$

キー概念はテーブル構造 $`(C, S, \Gamma)`$ に相対的に定義されます。「$`X`$ が、$`(C, S, \Gamma)`$ の超キーである」という意味の述語〈predicate〉を $`\text{isSuperkey}_{(C, S, \Gamma)}(X)`$ と書くことにします。この述語は次のように定義されます。

$`\For X \in \mrm{Pow}(C)\\
\Define \text{isSuperkey}_{(C, S, \Gamma)}(X) :\Iff \\
\quad \forall T \in \Gamma.\,
\lnot \exists t, t'\in T.\\
\qquad t \ne t' \land \pi_X(t) = \pi_X(t')
`$

定義のなかに否定($`\lnot`$)が出てくるのが嫌なら、次のように書き換えることができます*4

$`\For X \in \mrm{Pow}(C)\\
\Define \text{isSuperkey}_{(C, S, \Gamma)}(X) :\Iff \\
\quad \forall T \in \Gamma.\,
\forall t, t'\in T.\\
\qquad \pi_X(t) = \pi_X(t') \Imp t = t'
`$

超キーが定義できれば、それを使って候補キー〈candidate key〉を定義できます。「$`X`$ が、$`(C, S, \Gamma)`$ の候補キーである」という意味の述語を $`\text{isCandidateKey}_{(C, S, \Gamma)}(X)`$ と書くことにして:

$`\For X \in \mrm{Pow}(C)\\
\Define \text{isCandidateKey}_{(C, S, \Gamma)}(X) :\Iff \\
\quad \text{isSuperkey}_{(C, S, \Gamma)}(X)\\
\quad \land\\
\quad \lnot \exists Y \in \mrm{Pow}(C).\,
Y \subseteq X \land Y \ne X \land \text{isSuperkey}_{(C, S, \Gamma)}(Y)
`$

主キー〈primary key〉は、候補キーの集合からひとつ選んだ特定の候補キー $`K \subseteq C`$ のことです。

主キーを特定したテーブル構造は $`(C, S, \Gamma, K)`$ と書けます。主キー $`K`$ は候補キーなので、次の条件を満たします。

$`\forall T \in \Gamma.\,
\forall t, t'\in T.\, \pi_K(t) = \pi_K(t') \Imp t = t'\\
\land\\
\lnot \exists Y \in \mrm{Pow}(C).\\
\quad Y \subseteq K \land Y \ne K \land\\
\quad \forall T \in \Gamma.\,\forall t, t'\in T.\, \pi_Y(t) = \pi_Y(t') \Imp t = t'
`$

「うひゃー、長い論理式だ」と思ったかも知れません。自然言語〈日本語〉で書くと、もっと長くなり、しかも曖昧です。上記の長めの論理式は、正確に短く書いた表現であり、きちんとした推論のベースとして頼りになります。

暗黙の連想を前提にしたり、曖昧で雰囲気的な自然言語でお茶を濁していては、それに基づく正確な議論は無理です。明示的に、述語論理に基づいた表現を使うのが得策だと思います。

この記事では、テーブル構造の「キー」という概念を定義しただけです。さらに続く話があれば、「データベース::」という接頭辞が付いたタイトルの記事になるでしょう(次の記事がいつになるか分からんけど)。

*1:カラム関数 $`\pi_a`$ は、評価関数 $`\mrm{eval}(\hyp, \hyp)`$ の第二引数を固定した $`\mrm{eval}(\hyp, a)`$ と同じです。特定成分の値を取り出すことは、特定引数を渡して評価することです。

*2:存在命題の束縛変数名が、構成した2つのタプル $`t, t'`$ と同じ名前になっています。これは普通のことですが、混乱したり違和感を感じるなら、束縛変数名をリネームすればいいでしょう。例えば、$`\exists x, x' \in T.\, x \ne x' \land \pi_X(x) = \pi_X(x')`$

*3:テーブルスキーマ〈関係スキーマ〉において、その名前が重要視されるのは、「テーブルクラスを連想しやすい名前にすべき」というモラルがあるからでしょう。

*4:ド・モルガンの法則(限量子に対する法則も含める)と、$`A \Imp B`$ が $`\lnot A \lor B`$ と同値であることを使います。