使用适当的产品和属性关系

时间:2016-07-12 19:30:07

标签: database database-design

我即将为简单的电子商务平台实施数据库。我想实现以下内容:

  • 每个产品属于一个产品类别;

  • 每个产品类别都有自己的属性;

  • 每种产品对此产品类型的每个属性都有一个值。

我应该用什么关系存储这类信息?

2 个答案:

答案 0 :(得分:1)

这是逻辑模型 - 我理解它的方式;你应该能够调整它。

从中可以派生出物理模型和SQL代码。 KEY这里的单词意味着UNIQUE NOT NULL,您可以将它们用作主键。如果您选择将整数作为主键引入,请确保保持这些唯一。

请注意,一旦进入SQL,一切都应该是NOT NULL。

名为(CAT)的类别存在。

Category {CAT}
     KEY {CAT}

名为(ATR)的属性存在。

Attribute {ATR}
      KEY {ATR}

类别(CAT)具有属性(ATR)。

每个类别都有多个属性,同一属性可能属于多个类别。

CategoryAttribute {CAT, ATR}
              KEY {CAT, ATR}

产品名称(PRD)属于类别(CAT)。

每个产品只属于一个类别,每个类别可能包含多个产品。

 ProductCategory {PRD, CAT}
             KEY {PRD}
             KEY {PRD, CAT} -- seems redundant here, but is
                            -- needed for the FK from the next table

     FOREIGN KEY {CAT} REFERENCES Category {CAT}

来自类别(CAT)的产品(PRD)具有属于该类别的属性(ATR)。

对于属于某个类别的每个属性,该属性可能属于该类别中的多个产品。

ProductCategoryAttribute {PRD, CAT, ATR}

        KEY {PRD, CAT, ATR}
FOREIGN KEY {PRD, CAT} REFERENCES ProductCategory   {PRD, CAT}
FOREIGN KEY {CAT, ATR} REFERENCES CategoryAttribute {CAT, ATR}

答案 1 :(得分:0)

我不知道您使用的数据库平台,但对于少量产品,以及不依赖于每类别属性值的查询,我使用以下策略:

CREATE TABLE "Category" (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT
);

CREATE TABLE "Product" (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT,
  "categoryId" INTEGER NOT NULL REFERENCES "Category" ("id"),
  "attributes" TEXT NOT NULL
);

ER 1

在此示例中,类别主要用于强制参照完整性并提供导航类别列表。

属性作为JSON存储在attributes列中(大多数现代数据库倾向于本地支持此属性)。

如果所有类型产品共有任何属性,我们会在Product中创建特定列。例如,您可以添加creationDatedeletionDateprice或其他内容。

这使您可以执行典型Select * From Product Where id = @Id获取特定产品,Select * From Product Where categoryId = @CategoryId来获取所有类别的产品。

根据创建日期对creationDate进行排序可能很有用,如果需要,按类别过滤时,可以使用前N个。然而,对于数千种产品的少量产品,您可以按类别获取所有产品并在代码中执行此操作。

关于代码方面,像Dapper这样的产品有特定的扩展,可以帮助您处理这些受歧视的联合,但编写支持它的代码相当容易。这是一个怎样的方法。我会写伪C#,但我确信你可以适应。

我们有一个抽象类来处理Product表行

public abstract class ProductBase
{

   // only the fields in the Product table here

   public int CategoryId { get; set; }
   protected string Attributes { get; set; }

   // serialize extra fields to JSON in Attributes
   protected abstract void Prepare();

   // load the common fields from a data row
   protected static ProductBase(DataRow dr)
   {
      CategoryId = int.Parse(dr["categoryId"]);
      Attributes = dr["attributes"] as string;
   }

   // save to DB
   public void Save()
   {
      Prepare();

      // save to SQL
   }
}

我们每个类别都有特定的类,它们具有额外的属性并处理序列化和反序列化。

public class FooProduct: ProductBase
{
   public string Color { get; set; }

   protected override void Prepare()
   {
      Attributes = Json.Serialize(new { Color });
   }

   public FooProduct(DataRow dr): base(dr)
   {
      // we can only create foo products if the category is foo
      if (CategoryId != 23) throw new InvalidOperationException();

      var attr = Json.Deserialize(Attributes);
      Color = attr.Color;
   }
}

这个想法很有效,而你不需要得到" foo" Color的产品。如果你有能力得到所有" foo"产品和代码过滤,很棒。如果您的数据库理解JSON并允许您在Attributes字段内查询,那么除非服务器允许索引引用JSON序列化值,否则它将变得很慢。

如果所有其他方法都失败了,您需要创建一个索引表,其中包含颜色值和具有该颜色的产品的id s。这是相对痛苦的,除非你需要,否则你不想这样做(你现在也不想)。