试图避免多态关联

时间:2013-12-19 22:00:25

标签: mysql sql polymorphic-associations

我正在创建一个MySQL数据库,我遇到了一个我需要多态关联的实例......显然SQL不支持这个,所以我决定为每个外键创建一个列;发现如下:

CREATE TABLE mixers (
mixers_id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
0_booze_id INT(11),
0_gen_booze_id INT(11),
0_gen_soda_id INT(11),
0_soda_id INT(11),
1_booze_id INT(11),
1_gen_booze_id INT(11),
1_gen_soda_id INT(11),
1_soda_id INT(11),
2_booze_id INT(11),
2_gen_booze_id INT(11),
2_gen_soda_id INT(11),
2_soda_id INT(11),
3_booze_id INT(11),
3_gen_booze_id INT(11),
3_gen_soda_id INT(11),
3_soda_id INT(11),
4_booze_id INT(11),
4_gen_booze_id INT(11),
4_gen_soda_id INT(11),
4_soda_id INT(11),
5_booze_id INT(11),
5_gen_booze_id INT(11),
5_gen_soda_id INT(11),
5_soda_id INT(11),
6_booze_id INT(11),
6_gen_booze_id INT(11),
6_gen_soda_id INT(11),
6_soda_id INT(11),
7_booze_id INT(11),
7_gen_booze_id INT(11),
7_gen_soda_id INT(11),
7_soda_id INT(11),
8_booze_id INT(11),
8_gen_booze_id INT(11),
8_gen_soda_id INT(11),
8_soda_id INT(11),
9_booze_id INT(11),
9_gen_booze_id INT(11),
9_gen_soda_id INT(11),
9_soda_id INT(11),
FOREIGN KEY (0_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (1_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (2_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (3_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (4_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (5_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (6_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (7_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (8_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (9_booze_id) REFERENCES booze(booze_id),
FOREIGN KEY (0_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (1_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (2_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (3_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (4_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (5_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (6_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (7_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (8_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (9_gen_booze_id) REFERENCES gen_booze(gen_booze_id),
FOREIGN KEY (0_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (1_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (2_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (3_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (4_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (5_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (6_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (7_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (8_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (9_gen_soda_id) REFERENCES gen_soda(gen_soda_id),
FOREIGN KEY (0_soda_id) REFERENCES soda(soda_id),
FOREIGN KEY (1_soda_id) REFERENCES soda(soda_id),
FOREIGN KEY (2_soda_id) REFERENCES soda(soda_id),
FOREIGN KEY (3_soda_id) REFERENCES soda(soda_id),
FOREIGN KEY (4_soda_id) REFERENCES soda(soda_id),
FOREIGN KEY (5_soda_id) REFERENCES soda(soda_id),
FOREIGN KEY (6_soda_id) REFERENCES soda(soda_id),
FOREIGN KEY (7_soda_id) REFERENCES soda(soda_id),
FOREIGN KEY (8_soda_id) REFERENCES soda(soda_id),
FOREIGN KEY (9_soda_id) REFERENCES soda(soda_id)
)ENGINE=InnoDB;

我想做的是设置表格,以便每组成分 -

0_booze_id INT(11),
0_gen_booze_id INT(11),
0_gen_soda_id INT(11),
0_soda_id INT(11)
  • 只能使用一列(三列必须为null)或者一组中的所有四列都必须为空。

甚至可以创建这样的东西??? 如果没有,那么什么是更好的解决方案?

修改 为了澄清 - 我正在制作一个自动饮料混合机器人。我正在尝试创建一个数据库,允许在没有特定成分的情况下使用通用成分。

例如,如果食谱需要“杰克”和“可乐”,并且我有“杰克”和“可乐”成分,那么我会想要使用这些特定成分。但是,让我说我有一些我想用来代替可口可乐的品牌可乐。我希望专门针对“杰克”和“可口可乐”的食谱能够将“可口可乐”替换为“通用可乐”。

我的目的是创建两个通用表,一个用于苏打水,另一个用于豪饮“gen_soda”“gen_booze”。这些表格中包含“可乐”,“威士忌”,“伏特加”等物品。苏打水和酒精的表格将包含特定的成分名称,如“可乐”或“杰克丹尼尔斯”;然后将这些项目引用回其通用类型。

我最初发布的混音器表是包含机器人知道如何制作的各种混合饮料。应该提供的唯一混合饮料是具有特定成分的饮料。这就是我遇到多态关联这个术语的方式。

2 个答案:

答案 0 :(得分:2)

CREATE TABLE mixers (
    mixer_id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
    mixer_name VARCHAR(255) NOT NULL,
)

CREATE TABLE ingredients (
    ingredient_id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
    ingredient_name VARCHAR(255) NOT NULL,
)

CREATE TABLE mixer_ingredients
    mixer_id INT(11) NOT NULL,
    ingredient_id  INT(11) NOT NULL,
    PRIMARY KEY (mixer_id, ingredient_id),
    FOREIGN KEY (mixer_id) REFERENCES mixers(mixer_id),
    FOREIGN KEY (ingredient_id) REFERENCES ingredients(ingredient_id),
)

答案 1 :(得分:0)

我明白你要做什么,但认为这是错误的做法。您的数据模型需要更好地适应您的问题。

首先,从成分表开始,列表如下:

  • ingredientId
  • ingredientName
  • ingredientType

然后是MixedDrink表:

  • MixedDrinkId
  • MixedDrinkName

然后是MixedDrinkIngredient表:

  • MixedDrinkIngredientId
  • MixedDrinkId
  • IngredientId

因此,这可以处理混合饮料而无需替换。你是如何代表他们的?

那么,此时,您需要做出一些决定。成分的替换是泛型吗?或者某些MixedDrinks允许的替换是否允许,而其他人则不允许?根据这些问题的答案,替换信息可以包含MixedDrinkIngredientsIngredients或两者,具体取决于您需要的规则。

顺便说一句,豪饮和苏打水之间的区别嵌入type中的Ingredients信息中。这是一种简化,您可能实际上需要一个层次结构,在层次结构中的特定位置具有替换。例如,您可能愿意用百事可乐代替可口可乐,但不能用生姜啤酒代替。