PK制約について

DB設計におけるPK制約の役割やメリットなどを、DBFluteとの関わりを交えながら話題にします。

PK制約とは?

リレーショナルデータベースにおける基本中の基本なので、ここでは一般的な説明は割愛します。PK制約と DBFlute との関わり、そして、PK制約にまつわるよく議論される話題 複合主キーとサロゲートキー に関して分析してみたいと思います。

PK制約を推奨

DBFluteでは、必ずテーブルにPK制約を付与することが推奨されています。

不整合なデータほどリリース後の運用を悩ませるものはありません。 また、そのテーブルが何でユニークになるのか?それを制約として明示することは、ディベロッパーに業務仕様を伝える手段にもなります。 PK制約があることで、わざわざDB設計者に質問するまでもなく、そのテーブルのユニーク性を理解できます。

PK制約がないテーブルが存在するパターンを挙げてみます。

ユニークになるカラムがない
そもそもユニークになるカラムが存在しないパターンです。ピンポイントで検索するということができないテーブルで、通常あまりこういった状況は発生しません。 一件による更新や削除も同様です。業務的にもやれることが半減します。 万が一発生しても、代理キー(連番カラム)を導入することで、このパターンをなくすことはできます。 いざ、要らないと思っていたら後で一件更新などの要件が出てくるということを考えると、代理キーを導入することにためらう理由はあまり見当たりません。
this - 代理キー
PK制約のチェックコストを省略したいという考えもありますが、少なくとも2010年を過ぎた時点でのインフラ環境のパワーを考えたときに、 そのチェックコストを気にする必要のあるシステムは極少と考えられます(よほどの世界的なシステムでない限り)。 また、PK制約のチェックコストを気にするような場合は、そもそも別のことを考える必要があります。DBFluteどころか、Java や C# という部分も再考する必要があるかもしれません。
PK役割のカラムがあるのに単に制約がない
テーブルにはユニークになるPK役割のカラムがあるのにが制約が付与されていないパターンです。 不整合なデータが発生する可能性があります。また、そのカラムがPK役割であることは、人しか知りません。 すると、メタデータなどを利用して処理を行うツールなどでは、その便利さが半減する可能性があります(例えば、DBFluteではそうなります)
PK制約を付与する手間というのはほとんどないと言っていいので、業務仕様を表現するという意味合いでも、 せっかくのPK役割のカラムを活かすためにPK制約を付与するのにためらう理由はあまり見当たりません。 (PK制約のチェックコストに関しては、"ユニークになるカラムがない" パターンで述べたことと同じです)
代わりにユニーク制約を使っている
PK制約の代わりにユニーク制約を付与しているパターンです。 ユニーク制約は、一つのテーブルに複数付与できるものですが、ユニーク制約に対してFK制約を付与することもできます。
DBMSにはPK制約というテーブルでメインとなるユニークを表現する機能がサポートされています。 ユニーク制約で代理していると、ディベロッパーにはその意図が伝わりにくく、あまりメリットはないと考えられます。

既に述べられていますが、PK制約を付与する手間はほとんどなく、PK制約を付与するデメリットもほとんど見当たりません。

DBFluteでの扱い

DBFluteでは、PK制約がないテーブルに関しては デフォルトでは更新系メソッドが利用できない という制限があります。一件更新や一件削除ができないのは当然ですが(ユニークに絞り込みするカラムが判断できないため)、一件登録もできません。

もし、"PK役割のカラムがあるのに単に制約がない" もしくは "代わりにユニーク制約を使っている" パターンの場合は、実際にはユニークに絞り込みをするカラムがテーブルには存在するということになりますので、そのカラムが何なのか? をDBFluteに伝えることで更新系メソッドが利用できるようになります。AdditionalPrimaryKey で "どのカラムがPKなのか" を設定します。

また、"ユニークになるカラムがない" パターンの場合は、一件登録だけは利用できるようになるオプションがあります。 それ以外の処理が必要になった場合は外だしSQLで実装します。(結局、外だしSQLを使えば、大抵のことはできるというのに変わりはありません)

もちろん、これらは回避策でありメインの機能ではありません。 利用しているアプリも少ないと考えられるので、動作確認をしっかりした上で利用するようにして下さい。 (DBFluteのテストでもこのようなパターンのテストは多くはされていません)

PK制約の必須のチェック!?

そもそも、DBMS自体の仕様として、PK制約が必須でも良いと考えています。ただし、それができないのは仕方ありません。 長い歴史があり、多くの人に利用されているDBMSが今からPK制約を必須にすることはできません。

また、比較的新しい時期に誕生した DBFlute でも、PK制約がないテーブルがあった場合に例外にする、ということはしていません。 そういった DBMS の歴史から、万が一でも存在しないテーブルがあるかもしれないからです。 DBはアプリとは違い、変更し難いものです。不整合、もしくは、不整合リスクを許容して既に運用しているシステムもあるかもしれません。 そのシステムに DBFlute を適用する可能性もあります。(運用中にDB変更が頻繁に発生するシステムで、DBFluteが採用されるケースは珍しくありません)

それだけに、ツールでは思い切ったことができないため、その分、また新たにPK制約が存在しないDBも誕生します。 DBFluteでは、PK制約のないテーブルは デフォルトでは更新系メソッドが利用できない というささやかな制限でPK制約の重要性を表現しています。

PK制約における話題の中心

よく議論される話題のメインとしては、複合主キーと代理キーの扱い と考えられます。本当によく聞く話で話題が尽きません。 内容が大きいので、別のページにまとめています。