我正在设计一个数据库,我有很多产品,每个产品属于一个且只有一个类别。
产品应该被标记,但只允许标记属于它们所属的类别。
这是我到目前为止所得到的:
假设我有以下两类:
“智能手机”类别的标签:
“笔记本电脑”类别的标签:
此设计的问题在于数据库不会阻止产品被其他类别的标记标记:我的应用程序代码中的错误很容易导致笔记本电脑被标记为“双SIM卡”标记,这显然不是我想要的。
我想在数据库级别使用外键并且不使用触发器来防止这种情况。这有可能吗?
答案 0 :(得分: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
答案 1 :(得分:0)
我的答案与Ashuntosh A的答案非常相似,不同之处在于我会创建一个单独的表来将标签与类别相关联,这样架构就可以将标签应用于更多的类别(例如平板电脑)和手机可能有DualSim):
--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