我即将为简单的电子商务平台实施数据库。我想实现以下内容:
每个产品属于一个产品类别;
每个产品类别都有自己的属性;
每种产品对此产品类型的每个属性都有一个值。
我应该用什么关系存储这类信息?
答案 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
);
在此示例中,类别主要用于强制参照完整性并提供导航类别列表。
属性作为JSON存储在attributes
列中(大多数现代数据库倾向于本地支持此属性)。
如果所有类型产品共有任何属性,我们会在Product
中创建特定列。例如,您可以添加creationDate
,deletionDate
,price
或其他内容。
这使您可以执行典型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。这是相对痛苦的,除非你需要,否则你不想这样做(你现在也不想)。