一対一リレーションシップの設定時にはドラッグの向きに注意

 一対一リレーションシップにおける双方の主キーは完全に等価な関係にあるようにも見えますが、通常はどちらかのテーブルの主キーが先に発生し、もう一方がその値に従うこととなります。その意味では一対多リレーションシップと変わりなく、同じような親子関係にある(単に対応するレコードの数が異なるだけ)といえます。
 ただし、どちらが「親」なのかはリレーションシップの設定時に自動判定されるのではなく、利用者がリレーションシップを設定する時のドラッグの方向により決定されます(一対多リレーションシップの場合はテーブルの設定内容から自明なため自動判定されます)。
 リレーションシップといっても単に「線で結ぶ」だけであれば特段問題はありませんが、参照整合性を設定する場合には思わぬエラーにつながることがありますので注意が必要です。

f:id:accs2014:20180108213143p:plain:right:w600

 実例を見てみます。発送テーブルと受領テーブルの2つのテーブルがあり、それぞれ発送IDと受領IDが主キーとなっています。各地の事業所から集積地に向かって製品が送られる様子を記録するもので、製品を発送した際にはその内容を発送テーブルに記録し、集積地では製品を受け取った際にその内容を受領テーブルに記録します。この例では1回の発送が1回の受領に対応しており、対応関係としては一対一(リレーションシップ)となります。
 受領より発送の方が必ず先に発生しますので、受領IDの値は、発送IDの値のいずれかに一致しなければおかしい、ということになります。


f:id:accs2014:20180108024405p:plain:right:w400

 以上を踏まえて設定に移ります。まずはうまくいかない(エラーになる)例です。
 リレーションシップの設定画面でまず受領IDから発送IDに向かってドラッグしてみます。


f:id:accs2014:20180108024359p:plain:right:w400

 ウインドウが現れます。下部にあるように一対一リレーションシップであることは正しく判定されています。
 ここで、左上部には「テーブル/クエリ」、右上部には「リレーションテーブル/クエリ」と表示されているのに注意してください。

 参照整合性にチェックを入れ、「作成」をクリックすると…


f:id:accs2014:20180108024354p:plain:right:w600

 エラーとなります。
 なぜかといいますと上記の手順では受領IDの方が"親"と判断され、その結果、参照整合性による制約の内容が「発送IDの値は、受領IDの値のいずれかに一致しなければならない」というものになってしまったからです。これは正しくない制約ですが、その正しくない制約により、テーブルに記録されている(本来正しい)データをチェックしてしまったのです。

※どちらのテーブルにもレコードがない場合、この段階ではエラーは出ませんが、上記の誤った制約により、発送テーブルに行を追加できないという事態に陥ります。


f:id:accs2014:20180108024348p:plain:right:w400

 キャンセルして設定をやり直します。
 今度は発送IDから受領IDに向かってドラッグしてみます。


f:id:accs2014:20180108024510p:plain:right:w400

 ウインドウが現れます。
 先ほどと、表示されている主キーの名前が逆になっていることが分かります。

 参照整合性にチェックを入れ、「作成」をクリックすると…


f:id:accs2014:20180108024507p:plain:right:w400

 今度は無事に設定できました。
 「受領IDの値は、発送IDの値のいずれかに一致しなければならない」という正しい制約がかかり、テーブルの内容もそれに従っているからです。