2

我正在为我的公司创建一个数据库,该数据库将存储许多不同类型的信息。类别是亮度,对比度,色度等。每个类别都有一些我的公司想要开始存储的数据点。

通常,我会为每个类别创建一个表来存储相应的数据。(这就是我学会这样做的方式)。但是,有时这些类别有“子数据”,这会改变每个表中所需字段的数量。

那么我的问题是,人们在构建数据库时如何处理数据的不一致?他们只是继续为额外的数据添加更多表格,还是完全不同?

4

3 回答 3

2

关于关系数据库模型有一些(谢天谢地只有少数)不可更改的规则。其中之一是,如果您不知道要存储什么,则很难存储它。很有可能,您将更难检索它。

也就是说,业务规则的现实往往不如数据库设计的象牙塔那么清晰。最重要的是,您可能想要甚至需要一种在不更改架构的情况下引入新属性的方法。

这里有两种可行的方法:

  1. 使用专门用于松散或不存在模式(NoSQL 和朋友)的数据存储。详细解释这一点是 CS 论文的主题,而不是 stackoverflow 的答案。
  2. 我的建议:使用单独的属性表 - 这是怎么回事:

假设为了论证,您的产品总是有 (unique string) name, (integer) id, brightness, contrast,有时chromaticity加上(integer)和 (string) ,考虑这些表foobar

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)
);

现在您的“标准”属性将products像往常一样在表中,而“可选”属性将存储在product_properties引用产品 id 和属性 id 的行中,值在intvalueor中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

请理解,这会导致性能损失 - 事实上,您会在性能与灵活性之间进行交易:添加另一个属性只不过是在INSERTing 中插入一行properties,架构保持不变。

于 2012-06-26T21:55:34.270 回答
0

如果您不是 mysql 绑定,那么其他数据库具有表继承数组来解决某些特定情况。Postgresql是一个非常好的数据库,您可以像使用 mysql 一样轻松自由地使用它。

使用 mysql,您可以:

  1. 更改您的表,添加额外的列并在您不需要的子类别数据中允许 NULL。这种方式可以检查完整性,因为您仍然可以对列施加约束。除非您确实以这种方式拥有很多子类别列,否则我建议您这样做,否则选择 3。

  2. 将子类别数据动态存储在单独的表中,该表具有 category_id、category_row_id、subcategory 标识符(=子类别的类型)和值列:这样您就可以通过 category_id(确定表)和 category_row_id(链接到原始类别表行的PK)。坏事:你不能正确使用外键或约束来强制完整性,你需要编写毛茸茸的插入/更新触发器来仍然有一些控制,这将把完整性检查和引用检查的负担单独推到客户端上. (在这种情况下,您最好选择 NoSQL 路线)简而言之,我不推荐这样做。

  3. 您可以为每个类别表创建一个单独的子类别表,列可以通过值列 + 可选子类别标识符固定或可变,仍然可以使用外键,最好保持完整性是固定的,因为您将拥有完整的范围您可以使用的限制条件。如果您有很多子类别列,否则可能会弄乱您的常规子类别表,那么我建议将其与固定列一起使用。像之前的选项一样,我绝不建议对一次性数据以外的任何内容进行动态处理。

或者,如果您的子类别非常多变且易变:将NoSQL与文档数据库(如mongodb )一起使用,请注意,您可以将所有常规数据保存在适当的 RDBMS 中,并且只在文档数据库中存储侧数据,尽管这可能不推荐。

如果您的子类别数据处于已知的固定状态并且不易更改,我只需将额外的列添加到特定的类别表中。请记住,适当的 DBMS 的主要功能是通过检查和约束来保护数据的完整性,取消它从来都不是一个好主意。

于 2012-06-26T22:01:46.047 回答
0

如果您不限于 MySQL,您可以考虑使用 Microsoft SQL 服务器并使用稀疏列 这将允许您扩展架构以包含所需的任意数量的列,而不会对与给定行不相关的列产生存储损失。

于 2014-12-10T21:56:48.443 回答