« ドメイン特化基盤がドメインを豊かにする | トップページ | マイクロサービスで周辺アプリと連係する »

2015.11.29

値の変更が制限される項目「強属性」について

 一次識別子に含まれる項目であれば、登録後に値を変更することは許されない。それを許せば、一次識別子を基礎とするレコード間の対応関係が失われてしまうからだ。では、一次識別子に含まれない属性項目であれば、登録後に値を変更することは一般に許されるのか。否。値が変化するだけでアノマリー(更新時異状。不整合)を生じさせてしまう属性項目が存在する。それらについて仕様策定の管理レベルを上げて、アノマリーを回避しよう。

 以前に書いた記事(「フィールドの更新不可制約」の必要性)で、サロゲートキーを導入する際には、もともと認識されていた複合主キーに「ユニーク制約」とともに「更新制約」をかけておく必要があると説明した(かくのごとく、サロゲートキーというものは扱いがややこしい)。この他にも、独特な更新制約を受ける属性項目が存在する。

 例を挙げよう。商品の管理項目として「在庫管理対象フラグ」というものがあるとする。在庫管理対象と設定すれば、受払履歴が記録されるとともに在庫残高が更新される、そんな項目だとする。この項目の値を随時に変更出来るようではまずい。

 なぜか。たとえば、以前から取引されていたある商品を「在庫管理対象」から「在庫管理対象外」にいきなり変更したとする。すると、データベース上には「在庫管理対象外」の商品でありながら、在庫データや受払データが存在することになる。どちらの事実が正なのかわからないという典型的なアノマリーである。「在庫管理対象外」から「在庫管理対象」に変更することも、場合によってはやっかいだ。在庫管理対象外であるゆえに独特な扱いを受けてデータが展開されているとすれば、やはりアノマリーが生じる。

 商品の管理項目の中でも標準値系項目や摘要系項目については、アノマリーの心配はほとんどない。「ブランク/ゼロチェック」、「範囲値チェック」、「リスト値チェック」、「参照制約によるチェック」といった通常の妥当性検査のみで、値の妥当性を保全できる。いっぽう、ある種の項目は、その値にもとづいて広域のデータ状況が影響を受ける。それゆえ、妥当性検査どころではなく、そもそも値が変更されることそのものに制約がかかる。前者を「弱属性(weak attribute)」、後者を「強属性(strong attribute)」と呼ぼう。

 データ項目が「強属性」であるかどうかを意識的に見定め、そうであればその項目について仕様策定上の管理レベルを高め、アノマリーを未然に防ごうというのが私の提案である。これまでは、稼働後にユーザによる「思いもよらない更新」によってアノマリーが生じた段階で、受動的かつアドホックに対処されることが多かったと思う。こういう問題は、設計段階から周到に対処されるべきだ。

 「強属性」の更新制約に関する仕様化方針は、3つに大別できる。「更新の禁止」と「更新条件の組込み」と「付随処理の自動化」だ。それぞれを説明しよう。

 まず、もっとも簡素な方針が「更新の禁止」である。冒頭で説明したように、「サロゲートキー」の導入にともなって、もともと認識されていた複合主キーに対して更新不可制約をかける必要があった。登録時に値を設定したら、二度と更新できないようにするのである。強属性についてもそのように扱うことが許されるなら、開発者にとってはいちばん楽だ。その際には、上掲記事(「フィールドの更新不可制約」の必要性)の中で示したように、「更新不可項目」である旨を宣言的に扱えたら理想的である。

 とはいえ、データ設定に人間がかかわる限り、「登録ミス」が起こり得る。強引に更新不可項目にすれば、登録ミスが許されなくなる。それでは困るというのなら、「更新条件」を組込めばよい。すなわち、更新する際にデータ状況をチェックして、更新が許される状況であれば許し、そうでなければ禁止するようにする。

 その場合、データ状況がすでにそれを許さないにもかかわらず登録ミスを修正したい、という状況が起こり得る。そのときにはどのように対処したらいいのだろう。

 「在庫管理対象フラグ」をオンからオフに変更する例で説明しよう。まずユーザに在庫取引を引き起こした取引をキャンセルしてもらえば、受払が赤伝処理されて現在庫がゼロになる。その在庫データを削除してもらえば、システムは「在庫管理対象フラグ」を更新可能として示してくれるので、そこでオフに更新すればよい。その手順があまりに面倒に思えるほど在庫取引が起こっているのであれば、新しい商品データとして登録して、旧商品データを不活性化すればよい。

 強属性の仕様化方針の3つ目は、開発者にとっては手間がかかるが、ユーザにとっていちばん楽な「付随処理の自動化」だ。同じ例で説明しよう。「在庫管理対象フラグ」はいつでも変更可能で、オンからオフに変更することもオフからオンに変更することも自在とする。そのうえでシステムが、上述したようなユーザの一連の手順を、変更結果にしたがって自動的にやってしまうような仕掛けを組み込む。在庫データをクリアするプロセスなどはひどく「大技」な感じで現実的ではないが、データ状況の影響範囲がじゅうぶんに狭いのであれば仕様化は難しくない。

 なお、「強属性」はマスターテーブルに特有なものではない。念のために、トランザクション上やサマリー系テーブル上での例も示しておこう。

 まず、発注テーブル上には「仕入先ID」が置かれるが、これも強属性の例だ。さんざん入荷が起こった後で仕入先IDが変更されてしまえば、煩雑な赤黒訂正が必要になる。それを避けるためには、仕入先IDの変更が許されるのはせいぜい発注書を発行する前まで、といった制約を設けたらいい。ちなみに私なら、仕入先IDについては最初から更新不可項目にしてしまう。間違えたならその発注データを削除して、あらたに登録してもらえば済むからだ。

 つづいてサマリー系テーブルでの例だ。ロット在庫テーブル上の「在庫単価」も強属性である。その値は入荷時点で決定されるのだが、直後に入荷データを修正することで在庫単価は更新され得る。しかし、そのロットが一部でも出庫された後であれば、在庫単価の更新を許してはいけない。出庫分の受払実績上に出庫単価として転写されてしまっているからだ。原価情報として利用されている公算も高いので、それらを洗い替えるのもやっかいだ。もし出庫後にどうしても在庫単価を修正したいのであれば、関連する出庫取引をキャンセルしたうえで入荷データを修正し、あらためて出庫取引を登録すればよい。

 このように現場ではありがちな事象であるにもかかわらず、この種の知見がパブリックに語られることはまずない。その項目が「強属性」であるかどうかを意識するだけで、仕様策定上の疎漏は確実に減る。参考にしてほしい。

|

« ドメイン特化基盤がドメインを豊かにする | トップページ | マイクロサービスで周辺アプリと連係する »

コメント

ご無沙汰しています。

当社の若い技術者に言わせると、サロゲートキーにした方が、Select句を書くのに楽だと。
でもこの議事を読ませてみます。

どうも年寄には自然キーの方がイメージがわきます。

投稿: 盛田 | 2015.12.03 18:29

盛田さん、おひさしぶりです。

私は「自然キー主義者」ではないんですが、「サロゲートキー(単独主キー)主義者」の危うさはよくわかります。「複合主キーにすると、Select文のWhere条件が複雑になって、バグの温床となる」なんて、「鉄筋が多いと施工が複雑になって施工ミスの温床となる。ゆえに、柱1本あたり鉄筋1本とすべし」と言ってるようなもんです。

複合主キーは、実装の難易度で決まるものではなく、データ要件から導かれるものです。しかも、記事中では「サロゲートキーを導入する際には、もともと認識されていた複合主キーにユニーク制約と更新制約をかけるべし」と書いてますが、「サロゲートキー主義者」の多くは複合主キーを含めた形で本来のデータ要件を認識しようとしないので、危ういDB構造しか生み出せません。

投稿: わたなべ | 2015.12.03 19:04

渡辺様:

いつも興味深く読んでおります。
※渡辺様の本はほぼ持っています。(^-^;)

サロゲートキー主義者=単独主キー主義者
なのでしょうか?
コメントの内容は、テーブルには必ず単独項目の
主キーしか許さないという事について書かれているのですね。


現在、DB設計をしています。
商品マスタの設計で、商品CDの定義に迷っています。
現状のお客様はほとんど商品CDは数字なのですが、
将来的に文字の商品CDを使用する可能性もあるため、
別途、商品IDという項目を設け、主キーにしようと考えています。
また、在庫に関しては、商品ID+倉庫IDの2項目を
主キーとするテーブルを用意しようと考えています。

投稿: 森岡 | 2016.02.09 12:23

森岡さま

将来的に商品コードの体系が、既存の商品コードを含めて変わり得るということですよね。そうであれば、言われるように、PKとしての「商品ID」を内部識別用に置いて、商品コードは値変更可能なユニークキーとしたほうがいいと思います。必然的に在庫テーブルのPKは「商品ID+倉庫ID」になります。

これをサロゲートキー方式で設計すると、在庫テーブルのPKが「在庫ID」となるわけで、属性項目となる「商品ID+倉庫ID」の組み合わせにユニーク制約がかかっていなかったり、それらの値を更新するアプリが潜んでいたりします。すべてのテーブルのPKが「ID」なので、開発者にとっては実装しやすいのですが、ユーザにとっては地雷原のようなシステムです。

投稿: わたなべ | 2016.02.11 14:11

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: 値の変更が制限される項目「強属性」について:

« ドメイン特化基盤がドメインを豊かにする | トップページ | マイクロサービスで周辺アプリと連係する »