- PR -

1対1関連のテーブル設計について

投稿者投稿内容
nikori
会議室デビュー日: 2008/03/13
投稿数: 11
投稿日時: 2008-03-27 15:19
こんにちは。

みなさん、引き続きコメントありがとうございます。

カーニーさん
とても勉強になります。
RDBMSの実装に依存するのですね。

ちなみにHSQLDB(1.8.0)で試したところ、次のような結果になりました。
(NULL) != (NULL)
('A', 'B', NULL) != ('A', 'B', NULL)
(NULL, NULL, NULL) != (NULL, NULL, NULL)

引用:

一番混乱がないのは、NOT NULL列にしか一意制約を定義しない、ということになるのだと思います。


そうですね。
また、先に提示した仕様における「注目商品フラグ」カラムは
NOT NULLでboolean型にするのが明快と感じていたので、
制約はアプリ側で設けたいと思います。

コメントどうもありがとうございました。
nesc
会議室デビュー日: 2008/05/07
投稿数: 1
投稿日時: 2008-05-07 23:50
はじめまして。nescといいます。
ひと月以上前のスレッドへの書き込みで恐縮なのですが、
DB制約だけでできないかと思い、皆様の案を参考にしつつ 別案としてなんとか1つ考えてみました。
テーブルを4つ設ける方法です。
実装面(JOINのコストや実行スピード等)については考慮していません。

まず、カテゴリテーブルと商品テーブルは、あくまでマスタとして扱うようにします。
なので、「カテゴリテーブル」は最初にnikoriさんの提示されたものと同じで、
コード:
create table CATEGORY (
  ID  bigint,
  NAME varchar(32) not null,
  primary key(ID)
);


のようにし、
「商品テーブル」は
コード:
create table ITEM (
  ID bigint,
  NAME varchar(32) not null,
  primary key(ID)
); 


のようにします(カテゴリテーブルへのFKのカラムを外しました)。

つぎに、商品がカテゴリに所属(?)することをあらわす「所属テーブル」を設けます。
コード:
create table BELONG (
  CATEGORY_ID bigint,       // CATEGORYテーブルへのFK
  ITEM_ID bigint,           // ITEMテーブルへのFK
  primary key(CATEGORY_ID, ITEM_ID)
); 


こうすると、このテーブルへのレコード(CATEGORY_IDとITEM_IDの組)の有無そのものが、その組み合わせの"所属"が存在することを表すことになります。

ここでさらに、注目商品をあらわす「注目テーブル」を設けます。
(所属テーブルと同じように、このテーブルへのレコード(CATEGORY_IDとITEM_IDの組)の有無が、"注目"を表します。「期間」等の情報が必要であればこのテーブルにカラムを追加します。)
コード:
create table NOTICE (
  CATEGORY_ID bigint,       // CATEGORY_IDと、
  ITEM_ID bigint,           //  ITEM_IDの2つでBELONGテーブルへのFKとする(複合外部キー)
  primary key(CATEGORY_ID, ITEM_ID)
); 


そして、このテーブルのCATEGORY_IDに一意制約をつければ、「1つのカテゴリに最大1つの注目商品」 という要件が表せます。
 (べるさんのおっしゃる通り、注目商品が複数登録される仕様になれば、一意制約をとればよいです。)

それと同時に、「注目テーブル」から「所属テーブル」への複合外部キー制約によって、注目テーブルにあるレコード(CATEGORY_IDとITEM_IDの組)は必ず所属テーブルに存在します。
つまり、「異なるカテゴリのアイテムを注目商品にできない」ようになります。

と、いった感じです・・・。
大丈夫かな・・・問題あったら指摘していただけたらありがたいです。

スキルアップ/キャリアアップ(JOB@IT)