简体   繁体   中英

Many foreign keys in one lookup table. Bad idea?

I am using Django, and my tables look like

class Product(models.Model):
  category = models.CharField(max_length=50)
  title = models.CharField(max_length=200)

class Value(models.Model):
  name = models.CharField(max_length=200, unique=True)

class Attribute(models.Model):
  name = models.CharField(max_length=200)

  parent = models.ForeignKey('self', related_name='children')
  values = models.ManyToManyField(Value, through='ProductAttributeRelationship', related_name='values')  

  class Meta:
    unique_together = ('name', 'parent')

class ProductAttributeRelationship(models.Model):
  product = models.ForeignKey(Product, related_name='products')
  value = models.ForeignKey(Value, related_name='values')
  attribute = models.ForeignKey(Attribute, related_name='attributes')

  class Meta:
    unique_together = ('product', 'value', 'attribute', 'price')


class Price(models.Model):
  regular = models.IntegerField(blank=True, null=True)
  sale = models.IntegerField(blank=True, null=True)
  on_sale = models.NullBooleanField(blank=True)
  created = models.DateTimeField(auto_now=True)
  relation = models.ForeignKey(ProductAttributeRelationship)

  class Meta:
    unique_together = ('regular', 'sale', 'on_sale', 'sale_percentage')

Is it a bad idea to have the 3 ForeignKeys in ProductAttributeRelationship and the ForeignKey to that in Price since a ProductAttributeRelationship may have many prices? I don't have much knowledge in this area, and have been reading up about the 5 normalized forms, but am not sure where I should, or could, fit into the recommended 3rd form.

We declare a foreign key when a value for a subrow in one table has to appear as a value of a subrow in another table. That's what you have, so declare them.

Foreign keys have nothing to do with normalization per se. A normal form is something that a table is or isn't in. Normalization is about replacing a table by multiple tables that always join to it. A foreign key constraint holds when two tables have to agree per above. It can happen that new foreign keys holds between new tables from normalizing but if so you would just declare them. They don't affect what normal forms a table is in or normalization.

(Although ProductAttributeRelationship product, value, attribute and relationship are unique, presumably it is because product and price are unique, and product has just one price and an attribute has just one value. So you should say that product and price are unique; then all four have to be. Similarly, although Price regular, sale, on_sale and sale_percentage are unique, if regular, sale and on_sale are unique with sale_percentage a function of them then you should declare the three unique.)

(PS: 1. The main issue is integrity: If there is no constraint on the subset then invalid updates are allowed. 2. If the subset is unique then the superset is unique. So if the DBMS is enforcing subset uniqueness then it is enforcing superset uniqueness. 3. Moreover every superset of a CK is unique so there's nothing special about the particular extra columns you chose. 4. SQL DBMS UNIQUE/PK usually come with an index taking space and time to manage. For integrity and basic efficiency/optimization that's wasted on non-CK columns. But there can always be other special-case reasons for indexing. 5a. One reason to declare a non-CK superkey is that SQL forces you to do so to use it as a FK target. (You can either consider this redundancy as a helpful check or a tedious obtuseness.) 5b. Another reason is that sometimes this allows declarative (vs procedural/triggered) expression of integrity constraints via FK checking.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM