2017-08-10 70 views
1

我正在設計一個數據庫,其中有多個產品,每個產品都屬於一個且只有一個類別。關係數據庫設計問題 - 類別範圍標籤

產品的目的是要加標籤,但僅限於它們所屬類別的標籤。

這是我到目前爲止有:

database diagram

比方說,我有這2類:

  • 智能手機
  • 筆記本電腦

標籤爲「智能手機」類別:

  • 雙SIM
  • GPS

標籤爲 「筆記本電腦」 類別:

  • 背光鍵盤
  • HDMI

這種設計的問題是,該數據庫不會阻止產品從北ng用另一個類別的標籤標記:我的應用代碼中的一個錯誤很容易導致筆記本電腦被貼上「雙SIM」標籤,這顯然不是我想要的。

我想在數據庫級別防止這種情況與外鍵,而不使用觸發器。這可能嗎?

+0

爲什麼不只是把你的產品次要鑰匙?因此,雙SIM卡的產品ID爲X並且必須與類別ID Y等一起使用?那麼您不能重複使用不同類別的產品 - 但它可以解決您的需求。 – ssn

+0

對不起,我沒有明白。您是否建議在產品表中添加新的字段? – 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的「數據庫系統概念」。但是這本書解釋了一般數據庫概念,而不是關於特定DBMS的實用知識。它也很大。 –

0

我的答案是非常相似的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