一个查找表中有许多外键。馊主意?

时间:2015-02-02 04:59:36

标签: django database database-design orm relational-database

我正在使用Django,我的表格看起来像

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

ForeignKeys中的3 ProductAttributeRelationshipForeignKey中的Price置于ProductAttributeRelationship是不是一个坏主意,因为3rd可能有很多价格?我在这个领域没有太多的知识,并且一直在阅读有关5种规范化形式的内容,但我不确定我应该在哪里,或者可以适合推荐的{{1}}形式。

1 个答案:

答案 0 :(得分:1)

当一个表中的子行的值必须作为另一个表中的子行的值出现时,我们声明一个外键。这就是你所拥有的,所以宣告它们。

外键本身与规范化无关。普通表单是表格或不是表格。规范化是指将表格替换为始终加入表格的多个表格。当两个表必须按上述方式达成一致时,外键约束成立。可能会发生新的外键在规范化的新表之间保持,但如果是这样,你只会声明它们。它们不会影响表格的正常形式或正常化。

(虽然ProductAttributeRelationship产品,价值,属性和关系是独一无二的,可能是因为产品和价格是独一无二的,产品只有一个价格而且一个属性只有一个价值。所以你应该说产品和价格是唯一的那么所有四个都必须是。同样,虽然Price regular,sale,on_sale和sale_percentage是唯一的,如果regular,sale和on_sale是唯一的,sales_percentage是它们的函数,那么你应该声明这三个唯一的。)

(PS:1。主要问题是完整性:如果子集没有约束,则允许无效更新.2。如果子集是唯一的,则超集是唯一的。因此,如果DBMS强制执行子集唯一性,那么 强制执行超集唯一性.3。此外, CK的每个超集都是唯一的,因此您选择的特定额外列没有什么特别之处.4。SQL DBMS UNIQUE / PK通常带有一个占用空间和时间来管理的索引。为了在非CK列上浪费的完整性和基本效率/优化。但是索引总是有其他特殊原因.5a。一个声明非CK超级密钥的原因是SQL强制您将其用作FK目标。(您可以将此冗余视为有用的检查或繁琐的钝角。)5b。另一个原因是有时这允许通过FK检查声明(vs过程/触发)完整性约束的表达。)