Tom
Tom

Reputation: 3183

Having instance-like behaviour in databases

Sorry for the bad title, but I have no idea how to put this in short. The Problem is the following:

I have a generic item that represents a group, lets call it Car. Now this Car has attributes, that range within certain limits, lets say for example speed is between 0 and 180 for a usual Car. Imagine some more attributes with ranges here, for example Color is between 0 and 255 whatever that value might stand for.

So in my table GenericItems I have:

ID    Name

 1    Car

And in my Attributes I have:

ID   Name   Min_Value    Max Value
 1   Speed     0            180
 2   Color     0            255

The relation between Car and Attributes is thus 1:n.

Now I start having very specific instances of my Car for example a FordMustang, A FerrariF40, and a DodgeViper. These are specific instances and now I want to give them specific values for their attributes.

So in my table SpecificItem I have:

ID    Name           GenericItem_ID

 1    FordMustang         1
 2    DodgeViper          1
 3    FerrariF40          1

Now I need a third table SpecificAttributes2SpecificItems, to match attributes to SpecificItems:

ID    SpecificItem_ID   Attribute_ID   Value

 1         1                1           120        ;Ford Mustang goes 120 only
 2         1                2           123        ;Ford Mustang is red
 3         2                1           150        ;Dodge Viper goes 150
 4         2                2           255        ;Dodge Viper is white
 5         3                1           180        ;FerrariF40 goes 180
 6         3                2             0        ;FerrariF40 is black

The problem with this design is, as you can see, that I am basically always copying over all rows of attributes, and I feel like this is bad design, inconsistent etc. How can I achieve this logic in a correct, normalized way?

I want to be able to have multiple generic items, with multiple attributes with min/max values as interval, that can be "instantiated" with specific values

Upvotes: 0

Views: 167

Answers (4)

Anthony
Anthony

Reputation: 37065

Couple of ideas:

First, you should consider making your "genericgroups" table an "attribute" rather than something hovering above the rest of the data.

Second, you may have an easier time having each attribute table actually holding the attributes of the items, not simply the idea of the attributes. If you want to have a range, consider either an enum type (for item names) or simply an integer with a set maximum (so the value of the color_value column can't be above 255). This way you would end up with something more like:

  Item Table
   ID    Name 

    1    FordMustang 
    2    DodgeViper  
    3    FerrariF40

   ItemType Table:

   ItemID     Type
     1         Car
     2         Car
     3         Car


   ItemColor Table:

   ItemID     ColorID
     1         123
     2         255
     3           0

   MaxSpeed Table

   ItemID     MaxSpeedID

     1        120
     2        150
     3        180

Upvotes: 1

APC
APC

Reputation: 146239

There is a school of thought which holds that any attempt to build an EAV model in an RDBMS constitutes "bad design" but we won't go there. Ooops, looks like somebody else already has done.

I'm not certain what worries you. SpecificAttributes2SpecificItems is an intersection table (the clue is in the name). Necessarily it includes links to the Attributes and the SpecificItems. How could it not?

You probably need to have a MinVal and a MaxVal on SpecificAttributes2SpecificItems, as certain items will have a more limited range than that permitted by the GenericItems. For instance, everybody knows that Ferraris should only be available in red.

Upvotes: 1

Tangurena
Tangurena

Reputation: 2131

It looks like you're trying to replicate Entity Atribute Value as a design, which leads to a lot of ugly tables (well, usually it is one single table for everything).

http://en.wikipedia.org/wiki/Entity-attribute-value_model http://ycmi.med.yale.edu/nadkarni/Introduction%20to%20EAV%20systems.htm

Discussing EAV tends to lead to "religious wars" as there are very few good places to use it (many folks say there are zero good places) and there are other folks who think that since it is so very flexible, it should be used everywhere. If I can find the reference I'm looking for, I'll add it to this.

Upvotes: 1

pvoosten
pvoosten

Reputation: 3287

The easiest way to use inheritance in database models is to use an ORM tool. For Python there is SQLAlchemy, Django and others.

Now you should wonder whether e.g. a Ford Mustang is a kind of Car, or an instance of Car. In the former case, you should create a ford_mustang table defining the ford_mustang attributes. The ford_mustang table should then also have a foreign key to the car table, where the generic attributes of each FordMustang are specified. In the latter case, each kind of car is just a row in the Car table. Either way, each attribute should be represented in a single column.

Validation of the attributes is typically done in the business logic of the application.

Upvotes: 1

Related Questions