扩展关系数据库信息的最佳方式
Best way to extend information on a relational database
假设我们必须在数据库中存储不同类型产品的信息。但是,这些产品具有不同的规格。例如:
- Phone: cpu, ram, 存储...
- TV: 尺寸、分辨率...
我们希望将每个规格存储在一个 table 的列中,并且所有产品(无论类型)必须具有不同的 ID。
为了遵守这一规定,现在我有一个名为 Products
的通用 table(具有自动递增 ID)和一个下属 table 用于每种类型的产品(ProductsPhones
, ProductsTV
...) 与规格并与主体链接外键。
我发现此解决方案效率低下,因为 table Products
只有一列(自动递增 ID)。
我想知道是否有更好的方法使用关系数据库来解决这个问题。
虽然这不能完全按照关系来完成,但您仍然可以对表进行一些规范化,使其更容易编写代码。
您可以拥有这些表格:
-- what are the products?
Products (Id, ProductTypeId, Name)
-- what kind of product is it?
ProductTypes (Id, Name)
-- what attributes can a product have?
Attributes (Id, Name, ValueType)
-- what are the attributes that come with a specific product type?
ProductTypeAttributes (Id, ProductTypeId, AttributeId)
-- what are the values of the attributes for each product?
ProductAttributes (ProductId, ProductTypeAttributeId, Value)
所以对于 Phone 和电视:
ProductTypes (1, Phone) -- a phone type of product
ProductTypes (2, TV) -- a tv type of product
Attributes (1, ScreenSize, integer) -- how big is the screen
Attributes (2, Has4G, boolean) -- does it get 4g?
Attributes (3, HasCoaxInput, boolean) -- does it have an input for coaxial cable?
ProductTypeAttributes (1, 1, 1) -- a phone has a screen size
ProductTypeAttributes (2, 1, 2) -- a phone can have 4g
-- a phone does not have coaxial input
ProductTypeAttributes (3, 2, 1) -- a tv has a screen size
ProductTypeAttributes (4, 2, 3) -- a tv can have coaxial input
-- a tv does not have 4g (simple example)
Products (1, 1, CoolPhone) -- product 1 is a phone called coolphone
Products (2, 1, AwesomePhone) -- prod 2 is a phone called awesomephone
Products (3, 2, CoolTV) -- prod 3 is a tv called cooltv
Products (4, 2, AwesomeTV) -- prod 4 is a tv called awesometv
ProductAttributes (1, 1, 6) -- coolphone has a 6 inch screen
ProductAttributes (1, 2, True) -- coolphone has 4g
ProductAttributes (2, 1, 4) -- awesomephone has a 4 inch screen
ProductAttributes (2, 2, False) -- awesomephone has NO 4g
ProductAttributes (3, 3, 70) -- cooltv has a 70 inch screen
ProductAttributes (3, 4, True) -- cooltv has coax input
ProductAttributes (4, 3, 19) -- awesometv has a 19 inch screen
ProductAttributes (4, 4, False) -- awesometv has NO coax input
这不是完全相关的原因是您仍然需要评估属性的值类型(bool、int 等),然后才能在代码中以有意义的方式使用它。
简短的回答是否定的。关系模型是一个 first-order 逻辑模型,这意味着谓词可以随实体而变化,但不会随其他谓词而变化。这意味着不支持依赖类型和 EAV 模型。
EAV 模型在 SQL 数据库中是可能的,但它们不符合关系,因为 EAV 行中值字段的域取决于属性字段的值(有时取决于值实体字段也是如此)。实际上,EAV 模型往往查询和维护效率低下。
PostgreSQL 支持共享序列,这允许您确保唯一 auto-incremented ID 而无需公共超类型 table。但是,超类型 table 可能仍然是 FK 约束的好主意。
稍后您可能会发现您的 Products
table 有一些用途,可以用来保存 Type
、Serial number
、Cost
、[=14= 等常见属性], Number in stock
, Warehouse
, Supplier
, 等等...
有产品 table 很好。您可以将所有类型的所有通用列放在那里,例如产品名称、描述、成本、价格,仅举几例。所以它不仅仅是自动递增 ID。建议使用 int 或 long int 类型的内部 ID 作为主键。您还可以添加另一个字段 "code" 或任何您想为 user-entered 或 user-friendly 调用的字段,这在产品管理系统中很常见。如果用于搜索或查询条件,请确保将其编入索引。
HTH
假设我们必须在数据库中存储不同类型产品的信息。但是,这些产品具有不同的规格。例如:
- Phone: cpu, ram, 存储...
- TV: 尺寸、分辨率...
我们希望将每个规格存储在一个 table 的列中,并且所有产品(无论类型)必须具有不同的 ID。
为了遵守这一规定,现在我有一个名为 Products
的通用 table(具有自动递增 ID)和一个下属 table 用于每种类型的产品(ProductsPhones
, ProductsTV
...) 与规格并与主体链接外键。
我发现此解决方案效率低下,因为 table Products
只有一列(自动递增 ID)。
我想知道是否有更好的方法使用关系数据库来解决这个问题。
虽然这不能完全按照关系来完成,但您仍然可以对表进行一些规范化,使其更容易编写代码。
您可以拥有这些表格:
-- what are the products?
Products (Id, ProductTypeId, Name)
-- what kind of product is it?
ProductTypes (Id, Name)
-- what attributes can a product have?
Attributes (Id, Name, ValueType)
-- what are the attributes that come with a specific product type?
ProductTypeAttributes (Id, ProductTypeId, AttributeId)
-- what are the values of the attributes for each product?
ProductAttributes (ProductId, ProductTypeAttributeId, Value)
所以对于 Phone 和电视:
ProductTypes (1, Phone) -- a phone type of product
ProductTypes (2, TV) -- a tv type of product
Attributes (1, ScreenSize, integer) -- how big is the screen
Attributes (2, Has4G, boolean) -- does it get 4g?
Attributes (3, HasCoaxInput, boolean) -- does it have an input for coaxial cable?
ProductTypeAttributes (1, 1, 1) -- a phone has a screen size
ProductTypeAttributes (2, 1, 2) -- a phone can have 4g
-- a phone does not have coaxial input
ProductTypeAttributes (3, 2, 1) -- a tv has a screen size
ProductTypeAttributes (4, 2, 3) -- a tv can have coaxial input
-- a tv does not have 4g (simple example)
Products (1, 1, CoolPhone) -- product 1 is a phone called coolphone
Products (2, 1, AwesomePhone) -- prod 2 is a phone called awesomephone
Products (3, 2, CoolTV) -- prod 3 is a tv called cooltv
Products (4, 2, AwesomeTV) -- prod 4 is a tv called awesometv
ProductAttributes (1, 1, 6) -- coolphone has a 6 inch screen
ProductAttributes (1, 2, True) -- coolphone has 4g
ProductAttributes (2, 1, 4) -- awesomephone has a 4 inch screen
ProductAttributes (2, 2, False) -- awesomephone has NO 4g
ProductAttributes (3, 3, 70) -- cooltv has a 70 inch screen
ProductAttributes (3, 4, True) -- cooltv has coax input
ProductAttributes (4, 3, 19) -- awesometv has a 19 inch screen
ProductAttributes (4, 4, False) -- awesometv has NO coax input
这不是完全相关的原因是您仍然需要评估属性的值类型(bool、int 等),然后才能在代码中以有意义的方式使用它。
简短的回答是否定的。关系模型是一个 first-order 逻辑模型,这意味着谓词可以随实体而变化,但不会随其他谓词而变化。这意味着不支持依赖类型和 EAV 模型。
EAV 模型在 SQL 数据库中是可能的,但它们不符合关系,因为 EAV 行中值字段的域取决于属性字段的值(有时取决于值实体字段也是如此)。实际上,EAV 模型往往查询和维护效率低下。
PostgreSQL 支持共享序列,这允许您确保唯一 auto-incremented ID 而无需公共超类型 table。但是,超类型 table 可能仍然是 FK 约束的好主意。
稍后您可能会发现您的 Products
table 有一些用途,可以用来保存 Type
、Serial number
、Cost
、[=14= 等常见属性], Number in stock
, Warehouse
, Supplier
, 等等...
有产品 table 很好。您可以将所有类型的所有通用列放在那里,例如产品名称、描述、成本、价格,仅举几例。所以它不仅仅是自动递增 ID。建议使用 int 或 long int 类型的内部 ID 作为主键。您还可以添加另一个字段 "code" 或任何您想为 user-entered 或 user-friendly 调用的字段,这在产品管理系统中很常见。如果用于搜索或查询条件,请确保将其编入索引。
HTH