我遇到了一种情况,我需要通过 MariaDB 设计一个 SQL 数据库结构,但我不是数据库架构师,而且我想第一次尝试就做对。
因此,我有一个产品表,为了便于阅读,它有 2 个字段,id 和 name。我不知道如何制作这个图形,所以我将使用 json 来定义它:
productColumns = {
id: "INTEGER",
name: "STRING",
}
然后我有了变体表:
variantsColumns = {
id: "INTEGER",
name: "STRING",
product_id: "INTEGER",
}
现在的目标。我需要添加捆绑包和购物车。捆绑包必须包含具有指定变体的多个产品。购物车必须包含具有指定变体的多个产品以及捆绑包。现在我需要能够为购物车和捆绑包整体添加折扣,同时也能为购物车或捆绑包中的特定产品添加折扣。
我的想法是:
bundlesColumns: {
id: "INTEGER",
name: "STRING",
discount_type: "PERCENTAGE|ABSOLUTE"
discount: "INTEGER"
}
bundleItems: {
id: "INTEGER",
bundle_id: "INTEGER",
discount_type: "PERCENTAGE|ABSOLUTE",
discount: "INTEGER",
product_id: "INTEGER",
variant_id: "INTEGER",
quantity: "INTEGER",
}
carts: {
id: "INTEGER",
discount_type: "PERCENTAGE|ABSOLUTE"
discount: "INTEGER"
}
cartItems: {
id: "INTEGER",
cart_id: "INTEGER",
discount_type: "PERCENTAGE|ABSOLUTE",
discount: "INTEGER",
product_id: "INTEGER",
variant_id: "INTEGER",
bundle_id: "INTEGER",
quantity: "INTEGER"
}
我之前设计过几个数据库,但这种结构有些不对劲,看起来会给未来的发展带来麻烦,我想听听你的意见。有没有更好的方法?
您可以创建下表和索引
您的问题(您的“直觉”)与这种非规范化的设计有关:
这允许
cartItems
两种完全不同的事物:捆绑和单一产品。这是多态关联的一个例子。您现有的设计只能通过使用CHECK
约束来纠正这可能会使该表使用起来有些笨重,因为与其的连接可能是有条件的。
替代设计包括:
使
product_id
和成为variant_id
强制性的(不可空),并将三对(product_id, variant_id, bundle_id)
作为外键添加到bundleItems
。需要注意的是,
bundleItems
它是一个连接表,因此不应该有单独的id
列。相反,它的主键应该是由相同的三列组成的复合键。这种设计也有一个缺点,那就是你不能强制添加整个Bundle,而只能添加其中的一部分。
请注意缺少一
id
列,因为复合列表示主键。这种设计是最规范化的,但查询起来可能有点笨拙,因为您需要分别查询两个表并合并结果。
如果实际上只有少数项目需要捆绑,那么存储方面可能会相当繁重,但却最容易查询。