我正在为我的公司创建一个存储许多不同类型信息的数据库。类别包括亮度,对比度,色度等。每个类别都有一些我公司想要开始存储的数据点。
通常,我会为每个类别创建一个表,用于存储相应的数据。 (这就是我学会这样做的方式)。但是,有时这些类别具有“子数据”,这将改变每个表中所需的字段数。
我的问题是人们在构建数据库时如何处理数据的不一致?他们只是不断添加更多的表来获取额外的数据,还是完全不同的其他内容?
答案 0 :(得分:1)
关于关系数据库模型,有一些(并且非常感谢仅一些)不可修改的规则。其中之一是,如果您不知道要存储的 ,那么您很难存储它。有可能,你将更难以检索它。
尽管如此,业务规则的现实往往不如数据库设计的象牙塔那么明确。最重要的是,您可能希望甚至需要一种方法来引入新属性而无需更改架构。
以下是两种可行的方法:
假设为了论证,您的产品总是有(唯一字符串)name
,(整数)id
,brightness
,{{1} },contrast
加上有时(整数)chromaticity
和(字符串)foo
,请考虑这些表格
bar
现在,您的“标准”属性将照常放在CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
brightness INT,
contrast INT,
chromaticity INT,
UNIQUE INDEX(name)
);
CREATE TABLE properties (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
proptype ENUM('null','int','string') NOT NULL default 'null',
UNIQUE INDEX(name)
);
INSERT INTO properties VALUES
(0,'foo','int'),
(0,'bar','string');
CREATE TABLE product_properties (
id INT PRIMARY KEY AUTO_INCREMENT,
products_id INT NOT NULL,
properties_id INT NOT NULL,
intvalue INT NOT NULL,
stringvalue VARCHAR(250) NOT NULL,
UNIQUE INDEX(products_id,properties_id)
);
表中,而“可选”属性将存储在引用产品ID和属性ID的products
行中,值为product_properties
或intvalue
。
选择包含stringvalue
的产品(如果有)
foo
甚至
SELECT
products.*,
product_properties.intvalue AS foo
FROM products
LEFT JOIN product_properties
ON products.id=product_properties.product_id
AND product_properties.property_id=1
请理解,这会导致性能下降 - 实际上您会根据灵活性交换性能:添加另一个属性只不过SELECT
products.*,
product_properties.intvalue AS foo
FROM products
LEFT JOIN product_properties
ON products.id=product_properties.product_id
LEFT JOIN properties
ON product_properties.property_id=properties.id
WHERE properties.name='foo' OR properties.name IS NULL
INSERT
中的行,架构保持不变。< / p>
答案 1 :(得分:0)
如果你不是mysql绑定,那么其他数据库有table inheritance或arrays来解决某些特殊情况。 Postgresql是一个非常好的数据库,您可以像mysql一样轻松自如地使用它。
使用mysql你可以:
更改您的表,添加额外的列,并在您不需要的子类别数据中允许NULL。这样可以检查完整性,因为您仍然可以在列上添加约束。除非你真的有这样的 lot 子类别列,否则我建议这样做,否则选择3。
在一个单独的表中动态存储子类别数据,该表具有category_id,category_row_id,子类别标识符(=子类别的类型)和值列:这样您就可以通过category_id链接它来检索数据(确定table)和category_row_id(链接到原始类别表行的PK)。坏事:你不能正确地使用外键或约束来强制完整性,你需要编写毛茸茸的插入/更新触发器仍然有一些控制,这将完全支持客户端的完整性检查和参考检查的负担。 (在这种情况下,你可以更好地进入NoSQL路线)总之我不推荐这个。
您可以为每个类别表创建一个单独的子类别表,列可以通过值列固定或变量+可选的子类别标识符,仍然可以使用外键,最好保持完整性,因为您'我们将为您提供全方位的限制。如果您有一个 lot 的子类别列,否则会使您的常规子类别表混乱,那么我建议将其与固定列一起使用。像之前的选项一样,我绝不会建议除了一次性数据之外的任何动态。
或者,如果您的子类别非常易变且易变:使用NoSQL和文档数据库(例如mongodb),请注意您可以将所有常规数据保存在正确的RDBMS中,只保留存储数据在文档数据库中虽然可能不推荐。
如果您的子类别数据处于已知固定状态且不易更改,我只需将额外列添加到特定类别表中。请记住,正确的DBMS的主要特征是通过检查和约束来保护数据的完整性,废除它绝不是一个好主意。
答案 2 :(得分:0)
如果您不仅限于MySQL,则可以考虑使用Microsoft SQL Server并使用Sparse Columns这将允许您扩展架构以包含所需的多个列,而不会对不是的列产生存储损失对于给定的行是相关的。