Question

I'm creating a MySQL database and I ran into an instance in which I needed polymorphic associations... Obviously SQL does not support this, so I decided to create a column for each foreign key; found below:

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;

What I would like to do, is setup the table so that for each group of ingredients -

0_booze_id INT(11),
0_gen_booze_id INT(11),
0_gen_soda_id INT(11),
0_soda_id INT(11)
  • only one column can be used (three columns must be null) OR all four of a group must be null.

Is it even possible to create something like this??? If not, what would be a better solution?

EDIT For clarification - I'm making an automated drink mixing robot. I'm trying to create a database that allows the use of generic ingredients in the event that a specific ingredient is not available.

For example, if a recipe calls for "Jack" and "Coke", and I have the ingredients "Jack" and "Coke" available, then I would want to use those specific ingredients. However, lets say I have some off brand cola that I wish to use in place of Coke. I want the recipes that call specifically for "Jack" and "Coke" to be able to substitute "Coke" for "generic cola".

My intent was to create two generic tables, one for soda and one for booze "gen_soda" "gen_booze". These tables would contain items such as "Cola" "Whiskey" "Vodka". The tables soda and booze would contain specific ingredient names such as "Coke" or "Jack Daniels"; these items would then be referenced back to their generic types.

The mixers table that I originally posted about was to contain all the various mixed drinks that the robot would know how to make. The only mixed drinks that should be available are ones that have the specific ingredients available. This is how I came across the term polymorphic associations.

Was it helpful?

Solution

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),
)

OTHER TIPS

I understand what you are trying to do, but think it is the wrong approach. Your data model needs to better fit your problem.

First, start with an ingredients table, with columns like:

  • ingredientId
  • ingredientName
  • ingredientType

Then the MixedDrink table:

  • MixedDrinkId
  • MixedDrinkName

Then a the MixedDrinkIngredient table:

  • MixedDrinkIngredientId
  • MixedDrinkId
  • IngredientId

So, this handles the mixed drinks without substitutions. How do you represent them?

Well, at this point, you need to make some decisions. Is the substitution generic for the ingredient? Or is the substitution something allowed for some MixedDrinks but not others? Depending on the answers to these questions, the substitution information could go in MixedDrinkIngredients, Ingredients, or both, depending on the rules you need.

By the way, the distinctions between booze and soda is embedded in the type information in Ingredients. This is a simplification, you might actually want a hierarchy, with substitutions at particular places in the hierarchy. For example, you might be willing to substitute Pepsi for Coke, but not Ginger Ale.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top