mysql收藏夹项

vktxenjb  于 2021-06-20  发布在  Mysql
关注(0)|答案(3)|浏览(305)

当有多个表可供选择时,存储收藏夹的最有效方法是什么。
例如:您有一个用户(id,name,…)、食物(id,卡路里,…)、鸡尾酒(id,酒精,…)和糖果(id,name,…),用户可以从这些表中选择多个元素。解决这个问题的最好办法是什么。
我的想法是创建一个多对多关系,其中我有一个与上面的每个表(用户食物、用户鸡尾酒、用户糖果)相关的用户,或者一个最喜欢的表,其中我有上面提到的所有表的外键。
我想后者不是最佳解决方案。

vjrehmav

vjrehmav1#

您可以创建 Favorite 表和添加 FOREIGN KEY 从另外四张table
它看起来像:

CREATE TABLE User (`ID` int not null, `Name` varchar(5)) ;
INSERT INTO User (`ID`, `Name`) 
  VALUES (1, 'Jogn'), (2, 'Henry') ; 

CREATE TABLE Food (`ID` int, `calories` int) ; 
INSERT INTO Food (`ID`, `calories`) 
  VALUES (1, 123), (2, 456) ; 

CREATE TABLE Cocktails (`ID` int, `Alcoholic` int) ; 
INSERT INTO Cocktails (`ID`, `Alcoholic`) 
  VALUES (1, 30), (2, 40) ; 

CREATE TABLE Sweets (`ID` int, `Name` varchar(5)) ; 
INSERT INTO Sweets (`ID`, `Name`) 
  VALUES (1, 'candy'), (2, 'cake') ;

CREATE TABLE Favorite
    (`ID` int
     , `UserID` int not null
     , `FoodID` int 
     , `CocktailsID` int
     , `SweetsID` int
    )
;

ALTER TABLE `User` ADD CONSTRAINT PK_User PRIMARY KEY (`ID`);
ALTER TABLE `Food` ADD CONSTRAINT PK_Food PRIMARY KEY (`ID`);
ALTER TABLE `Cocktails` ADD CONSTRAINT PK_Cocktails PRIMARY KEY (`ID`);
ALTER TABLE `Sweets` ADD CONSTRAINT PK_Sweets PRIMARY KEY (`ID`);

ALTER TABLE `Favorite` ADD CONSTRAINT FK_Favorite_User
  FOREIGN KEY (`UserID`) REFERENCES `User`(`ID`); 
ALTER TABLE `Favorite` ADD CONSTRAINT FK_Favorite_Food
  FOREIGN KEY (`FoodID`) REFERENCES `Food`(`ID`); 
ALTER TABLE `Favorite` ADD CONSTRAINT FK_Favorite_Cocktails
  FOREIGN KEY (`CocktailsID`) REFERENCES `Cocktails`(`ID`); 
ALTER TABLE `Favorite` ADD CONSTRAINT FK_Sweetss
  FOREIGN KEY (`SweetsID`) REFERENCES `Sweets`(`ID`);   

INSERT INTO Favorite 
    (`ID`, `UserID`, `FoodID`, `CocktailsID`, `SweetsID`)
VALUES
    (1, 1, '1', NULL, NULL),
    (2, 2, NULL, '2', NULL),
    (3, 1, NULL, NULL, '1')
;

当我插入不存在的价值为糖果

INSERT INTO Favorite 
    (`ID`, `UserID`, `FoodID`, `CocktailsID`, `SweetsID`)
VALUES
    (3, 1, NULL, NULL, 4)
;

它将引发异常

Cannot add or update a child row: a foreign key constraint fails (`db_9_1a5d3f`.`favorite`, CONSTRAINT `FK_Sweetss` FOREIGN KEY (`SweetsID`) REFERENCES `sweets` (`ID`))

您可以通过以下sql脚本查询它们(可能创建一个视图):

select
  T1.ID FavoriteID,
  T1.`UserID`,
  case when T2.ID is not null then 'Food'
    when T3.ID is not null then 'Cocktails'
    when T4.ID is not null then 'Sweets'
  end type,
  COALESCE(T2.ID,T3.ID,T4.ID) ID  
from Favorite T1
left join Food T2 on T1.`FoodID` = T2.`ID`
left join Cocktails T3 on T1.`CocktailsID` = T3.`ID`
left join Sweets T4 on T1.`SweetsID` = T4.`ID`

| FavoriteID | UserID |      type | ID |
|------------|--------|-----------|----|
|          1 |      1 |      Food |  1 |
|          2 |      2 | Cocktails |  2 |
|          3 |      1 |    Sweets |  1 |

如果您想要测试:sql fiddle test demo链接

6ss1mwsb

6ss1mwsb2#

创建 favorite 表中的所有项类型都有一列。

CREATE TABLE favorite
             (user integer,
              item integer,
              item_type varchar(256),
              PRIMARY KEY (user,
                           item,
                           item_type),
              FOREIGN KEY (user)
                          REFERENCES user
                                     (id));
``` `item` 是相应表中的id( `food` ,  `cocktail` 或者 `sweet` ). `item_type` 以确保 `item` 对于不同类型的两个项目可以相等。例如,表名( `'food'` ,  `'cocktail'` 或者 `'sweet'` ). 它还可以作为一个辅助列来指定项目的类型 `item` 指向。
优势:
引入新项类型时,不需要更改架构。
添加和删除收藏夹不需要额外的逻辑,每个收藏夹一行——很简单。
缺点:
不能在上添加外键约束 `item` 因为它每行引用不同的表。您必须实现触发器以确保引用完整性。
创建 `favorite` 表中的每种项目类型都有一列。

CREATE TABLE favorite
(id integer
AUTO_INCREMENT,
user integer,
food integer,
cocktail integer,
sweet integer,
PRIMARY KEY (id),
FOREIGN KEY (food)
REFERENCES food
(id),
FOREIGN KEY (cocktail)
REFERENCES cocktail
(id),
FOREIGN KEY (sweet)
REFERENCES sweet
(id),
UNIQUE (user,
food),
UNIQUE (user,
cocktail),
UNIQUE (user,
sweet));

优势:
可以使用外键约束。
缺点:
当引入新的项类型时,需要更改架构。
如果用户可以拥有任意数量的每种项目类型的收藏夹,这会变得有点复杂。然后需要为用户提供更多的行。i、 例如,当添加新收藏夹时,必须检查是否可以更新现有行,其中收藏夹类型的相应列为空,或者是否需要插入新行,因为对于用户来说,相应列在所有行中已经不是空的。删除收藏夹时,请单击“全部” `NULL` s行可能应该删除。这需要应用程序中的额外逻辑,或者必须封装在触发器或过程中。
如果每个项目类型只能有一个收藏夹,那么这可能是一个不错的选择。
介绍一个常见的 `item` 并让不同的项表引用该公共表。收藏夹表将只引用常用表。

CREATE TABLE item
(id integer
AUTO_INCREMENT,
PRIMARY KEY (id));

INSERT INTO item
SELECT NULL
FROM food
UNION ALL
SELECT NULL
FROM cocktail
UNION ALL
SELECT NULL
FROM sweet;

ALTER TABLE food
ADD (item integer,
FOREIGN KEY (item)
REFERENCES item
(id));
ALTER TABLE cocktail
ADD (item integer,
FOREIGN KEY (item)
REFERENCES item
(id));
ALTER TABLE sweet
ADD (item integer,
FOREIGN KEY (item)
REFERENCES item
(id));

UPDATE food
SET item = (SELECT count()
FROM food s
WHERE s.id <= food.id);
UPDATE cocktail
SET item = (SELECT count(
)
FROM cocktail s
WHERE s.id <= food.id)
+ (SELECT count()
FROM food);
UPDATE sweet
SET item = (SELECT count(
)
FROM sweet s
WHERE s.id <= food.id)
+ (SELECT count()
FROM food)
+ (SELECT count(
)
FROM cocktail);

ALTER TABLE food
MODIFY item integer
NOT NULL;
ALTER TABLE cocktail
MODIFY item integer
NOT NULL;
ALTER TABLE sweet
MODIFY item integer
NOT NULL;

CREATE TABLE favorite
(user integer,
item integer,
PRIMARY KEY (user,
item),
FOREIGN KEY (user)
REFERENCES user
(id),
FOREIGN KEY (item)
REFERENCES item
(id));

(可选)可以在中添加助手列 `item` 指定项目类型的步骤 `id` . 也可以选择放弃 `id` 从不同的项目表( `food` ,  `cocktail` 或者 `sweet` )使用 `item` 作为主键。
优势:
引入新项类型时,不需要更改架构。
可以使用外键约束。
添加和删除收藏夹不需要额外的逻辑,每个收藏夹一行——很简单。
缺点:
介绍起来有点棘手。
可能需要更改现有的应用程序逻辑,因为任何类型的项现在都需要在 `item` 创建时。也可以由某个触发器处理--实际上它只需要创建一个新的 `item.id` 以满足相应项表中的外键约束( `food` ,  `cocktail` 或者 `sweet` ),所以它相当简单。
总的来说可能是“最干净”的解决方案。
x9ybnkn6

x9ybnkn63#

你基本上有两个选择:

create table favorites (
    favoritesId int auto_increment primary key,
    userId,
    which varchar(255),
    id int,
    foreign key (userId) references users(userId)
);

这是简短、简洁的,允许您添加新的实体。
或者,您可以分别列出每一项:

create table favorites (
    favoritesId int auto_increment primary key,
    foodId int,
    cocktailsId int,
    . . .
    foreign key (userId) references users(userId),
    foreign key (foodId) references foods(foodId),
    foreign key (cocktailsId) references cocktails(cocktailsId),
    . . .
);

这不太简洁,但允许添加显式外键引用。如果需要的话,它还可以很容易地在一行中表示多个收藏夹。

相关问题