2017-08-10 6 views
1

私は数多くの製品があり、それぞれが唯一のカテゴリーに属するデータベースを設計しています。リレーショナルデータベース設計の問題 - カテゴリースコープのタグ

商品にはタグが付いていますが、属する商品カテゴリに許可されているタグのみが商品になります。

これは私がこれまで持っているものです:

  • スマートフォン
  • ノート

タグ用:

database diagram

だが、私はこれらの2つのカテゴリーがあるとしましょう「スマートフォン」カテゴリ:

  • デュアルSIM
  • GPS "ラップトップ" カテゴリの

タグ:

  • バックライト付きキーボード
  • HDMI

この設計に問題があることですデータベースは製品をbeiから保護しません別のカテゴリのタグでタグ付けされていると、アプリのコードのバグにより、ノートパソコンに「デュアルSIM」タグが付いてしまうことがあります。これは明らかに私が望むものではありません。

私はこのような状況を、外部キーを持つデータベースレベルで、トリガーを使用しないで回避したいと考えています。これはまったく可能ですか?

+0

ちょうどあなたの製品の二次キーに入れていないのはなぜ?したがって、デュアルSIMには製品ID Xがあり、カテゴリID Yなどで使用する必要がありますか?次に、さまざまなカテゴリの製品を再利用することはできませんが、それはあなたのニーズを解決します。 – ssn

+0

申し訳ありませんが、私はそれを取得していません。 productsテーブルに新しいフィールドを追加することをお勧めしますか? – kYuZz

+0

はい。あなたの商品/タグが特定のカテゴリに属する​​ようにします。これは、新しい商品/タグをカテゴリに追加するときに維持されます – ssn

答えて

3

Oracleでは次のことができました。最後のインサートがどのように失敗するかに注意してください。

CREATE TABLE product (
    id   INTEGER NOT NULL, 
    category_id INTEGER NOT NULL, 
    PRIMARY KEY (id), 
    CONSTRAINT uq_prod_cat UNIQUE (id,category_id) 
); 

INSERT INTO product (
    id, 
    category_id 
) VALUES (
    1, 
    1 
); 

CREATE TABLE tags (
    id   INTEGER NOT NULL, 
    category_id INTEGER NOT NULL, 
    PRIMARY KEY (id), 
    CONSTRAINT uq_tag_cat UNIQUE (id,category_id) 
); 

INSERT INTO tags (
    id, 
    category_id 
) VALUES (
    1, 
    1 
); 

INSERT INTO tags (
    id, 
    category_id 
) VALUES (
    2, 
    1 
); 

INSERT INTO tags (
    id, 
    category_id 
) VALUES (
    3, 
    2 
); 

CREATE TABLE product_tags (
    id   INTEGER NOT NULL, 
    product_id INTEGER NOT NULL, 
    category_id INTEGER NOT NULL, 
    tag_id  INTEGER NOT NULL, 
    PRIMARY KEY (id), 
    FOREIGN KEY (product_id,category_id) 
     REFERENCES product (id,category_id), 
    FOREIGN KEY (tag_id,category_id) 
     REFERENCES tags (id,category_id) 
); 

INSERT INTO product_tags (
    id, 
    product_id, 
    category_id, 
    tag_id 
) VALUES (
    1, 
    1, 
    1, 
    1 
); 

1 row inserted. 

INSERT INTO product_tags (
    id, 
    product_id, 
    category_id, 
    tag_id 
) VALUES (
    2, 
    1, 
    1, 
    2 
); 

1 row inserted. 

INSERT INTO product_tags (
    id, 
    product_id, 
    category_id, 
    tag_id 
) VALUES (
    3, 
    1, 
    1, 
    3 
); 

Error starting at line : 35 in command - 
INSERT INTO product_tags (id, product_id, category_id, tag_id) VALUES (3, 1, 1, 3) 
Error report - 
ORA-02291: integrity constraint (SYS_C008023) violated - parent key not found 
+0

本当に良い答えです。私はこれをさらに学ぶことができる本をお勧めできるかどうか疑問に思っていましたか? – kYuZz

+0

データベースについては、Henry F. Korthの「Database System Concepts」をお勧めします。しかし、これは、特定のDBMSに関する実用的な知識ではなく、一般的なデータベースの概念を説明する本です。それはまた非常に大きい。 –

0

スキーマがより1つのカテゴリ(例えば、両方のタブレットに適用するタグを可能にしているので、私は、カテゴリとタグを関連付けるための別のテーブルを作成した以外は私の答えは、Ashuntosh Aのものとかなり似ていますそして、電話が)DualSimを持つことができます:

diagram

--TSQL 

create table ProductCategory 
(
    id int primary key identity, 
    name varchar(50) not null 
) 

create table ProductTag 
(
    id int primary key identity, 
    name varchar(50) not null 
) 

create table TagCategory 
(
    tag_id int foreign key references ProductTag, 
    category int foreign key references ProductCategory, 
    primary key (tag_id, category) 
) 

create table Product 
(
    id int primary key identity, 
    type int foreign key references ProductCategory, 
    unique (id, type) 
) 

create table TaggedProduct 
(
    product int, 
    tag int, 
    type int, 
    primary key (product, tag), 
    foreign key (product, type) references Product (id, type), 
    foreign key (tag, type) references TagCategory (tag_id, category) 
) 



insert ProductCategory 
    select 'Laptop' union 
    select 'Phone' 

insert ProductTag 
    select 'HDMI' union 
    select 'Backlit Keyboard' union 
    select 'Dual Sim' union 
    select 'GPS' 

insert TagCategory 
    select 1, 1 union -- HDMI/LAPTOP 
    select 2, 1 union -- Backlit/LAPTOP 
    select 3, 2 union -- DualSim/PHONE 
    select 4, 2 -- GPS/PHONE  

insert Product 
    select 1 --a laptop 

insert TaggedProduct 
    select 1, 1, 1 --laptop has hdmi 
    union select 1, 2, 1 --laptop has backlit keyboard 

insert TaggedProduct select 1, 3, 1 
--fails because 'DualSim/Laptop' is not a valid category 
+0

も良い答えですが、私の特定のケースではカテゴリ間でタグを共有する必要はありません – kYuZz

関連する問題