每个客户有选择地覆盖主数据的数据库结构

cop*_*360 5 sql database data-modeling

对于这个问题,请考虑使用多租户数据库的应用程序,其中包含制造商和模型的建模.如果我们谈论汽车,那么制造商将是福特,雪佛兰,宝马等,而型号将是F-150,Camaro和M3.

模型与制造商的关系是多对一的.使用customer_id分隔每个租户的数据.

数据模型的要求:

  • 可以在主级别定义制造商和模型,以使其可供所有客户使用
  • 客户选择他们想要使用的主要实体
  • 客户可以覆盖主模型或制造商的属性
  • 客户可以创建自己的制造商
  • 客户可以为自己或主制造商创建自己的模型
  • 模型中的其他实体将与这些实体相关,因此希望每个主表可以为外键创建一个主表.制造商和模型表填充了该示例中的角色.

在这个例子中:

  • 客户1使用福特原样,超越雪佛兰,并增加了两个定制制造商
  • 客户1按原样使用雪佛兰和宝马,并增加了一个定制生产商
  • 根据脚本中的注释创建模型

以下是符合所有要求的带注释的示例实现.

  • 如何改进?
  • 在这些关系的其他方面可以建模吗?

制造商表格

/*
 * Master manufacturers shared between all customers
 */
CREATE TABLE master_manufacturers (
    master_manufacturer_id INTEGER NOT NULL,
    name VARCHAR(100) NOT NULL,
    attribute_1 VARCHAR(50),
    /* ... */
    attribute_n VARCHAR(50),
    PRIMARY KEY (master_manufacturer_id)
);

INSERT INTO
    master_manufacturers (master_manufacturer_id, name)
VALUES
    (1, 'Ford'),
    (2, 'Chevrolet'),
    (3, 'BMW');

/*
 * A Customer's manufacturer.  
 *   If master_manufacturer_id IS NULL, then it is a custom manufacturer and manufacturer_custom contains the data
 *   If master_manufacturer_id IS NOT NULL and manufacturer_custom does not exist, then the master is used without modification
 *   If master_manufacturer_id IS NOT NULL and manufacturer_custom exists, then the master is overridden
 */
CREATE TABLE manufacturers (
    manufacturer_id INTEGER NOT NULL,
    customer_id INTEGER NOT NULL,
    master_manufacturer_id INTEGER,
    PRIMARY KEY (manufacturer_id),
    FOREIGN KEY (master_manufacturer_id) REFERENCES master_manufacturers (master_manufacturer_id),
    UNIQUE (customer_id, master_manufacturer_id)
);

INSERT INTO
    manufacturers (manufacturer_id, customer_id, master_manufacturer_id)
VALUES
    (1, 1, 1),
    (2, 1, 2),
    (3, 1, NULL),
    (4, 1, NULL),
    (5, 2, 2),
    (6, 2, 3),    
    (7, 2, NULL);    

CREATE TABLE manufacturer_custom (
    manufacturer_id INTEGER NOT NULL,
    name VARCHAR(100) NOT NULL,
    attribute_1 VARCHAR(50),
    /* ... */
    attribute_n VARCHAR(50),
    PRIMARY KEY (manufacturer_id),
    FOREIGN KEY (manufacturer_id) REFERENCES manufacturers (manufacturer_id)
);

INSERT INTO
    manufacturer_custom (manufacturer_id, name)
VALUES
    (2, 'Chevy'),
    (3, 'Cust 1 Custom 1'),
    (4, 'Cust 1 Custom 2'),
    (7, 'Cust 2 Custom 1');
Run Code Online (Sandbox Code Playgroud)

模型表

/*
 * Master models shared between all customers
 */
CREATE TABLE master_models (
    master_model_id INTEGER NOT NULL,
    master_manufacturer_id INTEGER NOT NULL,
    name VARCHAR(100) NOT NULL,
    attribute_1 VARCHAR(50),
    /* ... */
    attribute_n VARCHAR(50),
    PRIMARY KEY (master_model_id),
    FOREIGN KEY (master_manufacturer_id) REFERENCES master_manufacturers (master_manufacturer_id)
);

INSERT INTO
    master_models (master_model_id, master_manufacturer_id, name)
VALUES
    (1, 1, 'F-150'),
    (2, 1, 'F-250'),
    (3, 1, 'Falcon'),
    (4, 2, 'Camaro'),
    (5, 2, 'Corvette'),
    (6, 3, 'M3'),
    (7, 3, '135i');

/*
 * A Customer''s model.  
 *   If master_model_id IS NULL, then it is a custom model and model_custom contains the data
 *   If master_model_id IS NOT NULL and model_custom does not exist, then the master is used without modification
 *   If master_model_id IS NOT NULL and model_custom exists, then the master is overridden
 */
CREATE TABLE models (
    model_id INTEGER NOT NULL,
    master_model_id INTEGER,
    manufacturer_id INTEGER NOT NULL,
    attribute_1 VARCHAR(50),
    /* ... */
    attribute_n VARCHAR(50),
    PRIMARY KEY (model_id),
    FOREIGN KEY (master_model_id) REFERENCES master_models (master_model_id)
);

INSERT INTO
    models (model_id, master_model_id, manufacturer_id)
VALUES
    (1, 1, 1),    /* F-150 for customer_1's Ford */
    (2, 2, 1),    /* F-250 for customer_1's Ford */
    (3, 4, 2),    /* Camaro for customer_1's Chevy */
    (4, 4, 5),    /* Camaro for customer_2's Chevrolet */
    (5, 5, 5),    /* Corvette for customer_2's Chevrolet */
    (6, 6, 6),    /* M3 for customer_2's BMW */
    (7, NULL, 1), /* F-350 (custom) for customer_1's Ford */
    (8, NULL, 6), /* M7 (custom) for customer_2's BMW */
    (9, NULL, 7); /* Custom Model (custom) for customer_2's Custom Mfg */

CREATE TABLE model_custom (
    model_id INTEGER NOT NULL,
    name VARCHAR(100) NOT NULL,
    attribute_1 VARCHAR(50),
    /* ... */
    attribute_n VARCHAR(50),
    PRIMARY KEY (model_id),
    FOREIGN KEY (model_id) REFERENCES models (model_id)
);

INSERT INTO
    model_custom (model_id, name)
VALUES
    (7, 'F-350'),        /* F-350 for customer_1's Ford */
    (8, 'M7'),           /* M7 for customer_2's BMW */
    (9, 'Custom Model'); /* Custom Model for customer_2's Custom Mfg */
Run Code Online (Sandbox Code Playgroud)

用于简化使用这些表的视图

/*
 * View for a customer''s manufacturers
 */
CREATE VIEW vw_manufacturers AS
    SELECT
        m.customer_id,
        m.manufacturer_id, 
        COALESCE(cm.name, mm.name) AS name,
        COALESCE(cm.attribute_1, mm.attribute_1) AS attribute_1,
        /* ... */
        COALESCE(cm.attribute_n, mm.attribute_n) AS attribute_n
    FROM
        manufacturers m
    LEFT JOIN
        master_manufacturers mm
    USING
        (master_manufacturer_id)
    LEFT JOIN
        manufacturer_custom cm
    USING
        (manufacturer_id);

/*
 * View for a customer's models
 */
CREATE VIEW vw_models AS
    SELECT
        mfg.customer_id,
        mfg.manufacturer_id,
        mfg.name AS manufacturers_name,
        m.model_id,
        COALESCE(cm.name, mm.name) AS name,
        COALESCE(cm.attribute_1, mm.attribute_1) AS attribute_1,
        /* ... */
        COALESCE(cm.attribute_n, mm.attribute_n) AS attribute_n
    FROM
        vw_manufacturers mfg,
        models m
    LEFT JOIN
        master_models mm
    USING
        (master_model_id)
    LEFT JOIN
        model_custom cm
    USING
        (model_id)
    WHERE
        mfg.manufacturer_id = m.manufacturer_id;
Run Code Online (Sandbox Code Playgroud)

customer_id的制造商1

SELECT manufacturer_id, name FROM vw_manufacturers WHERE customer_id = 1;

 manufacturer_id |      name       
-----------------+-----------------
           1 | Ford
           2 | Chevy
           3 | Cust 1 Custom 1
           4 | Cust 1 Custom 2
Run Code Online (Sandbox Code Playgroud)

customer_id的制造商2

SELECT manufacturer_id, name FROM vw_manufacturers WHERE customer_id = 2;

 manufacturer_id |      name       
-----------------+-----------------
           5 | Chevrolet
           6 | BMW
           7 | Cust 2 Custom 1
Run Code Online (Sandbox Code Playgroud)

customer_id的模型1

SELECT * FROM vw_models WHERE customer_id = 1;

 customer_id | manufacturer_id | manufacturers_name | model_id |  name  
-------------+-----------------+--------------------+----------+--------
       1 |               1 | Ford               |        1 | F-150
       1 |               1 | Ford               |        2 | F-250
       1 |               2 | Chevy              |        3 | Camaro
       1 |               1 | Ford               |        7 | F-350
Run Code Online (Sandbox Code Playgroud)

customer_id的模型2

SELECT * FROM vw_models WHERE customer_id = 2;

 customer_id | manufacturer_id | manufacturers_name | model_id |     name     
-------------+-----------------+--------------------+----------+--------------
           2 |               5 | Chevrolet          |        4 | Camaro
           2 |               5 | Chevrolet          |        5 | Corvette
           2 |               6 | BMW                |        6 | M3
           2 |               6 | BMW                |        8 | M7
           2 |               7 | Cust 2 Custom 1    |        9 | Custom Model
Run Code Online (Sandbox Code Playgroud)

OMG*_*ies 2

您需要以下表格:

  • 制造商代码
  • 制造商类型代码
  • 制造商详情
  • 型号代码
  • 型号-类型-代码
  • 型号详情

如果您有具有相同数据的表 - 您需要合并它们,并使用 TYPE_CODE 表来区分它们。

回复:制造商和客户 目前,您需要 PK 为 MANUFACTURER-ID 和 CUSTOMER-ID。最好将制造商分为制造商代码和制造商详细信息。制造商代码将包含“BMW”、“FORD”等以及自定义代码。制造商详细信息将允许您保留每个客户的详细数据,同时允许您重复使用“BMW”等代码。模型也是如此。

下一步是为发动机、车轮等定义类型代码表。我将使用称为模型属性的 XREF 表将这些与模型详细信息相关联。MODEL-ATTRIBUTES 表将包含:

  • 型号-详细信息-ID(pk)
  • 型号-属性-类型-代码 (pk)
  • 属性代码(pk)

这将允许可选模型属性与适用的模型详细信息记录相关联,而无需不断向模型详细信息表添加属性。

制造商代码

  • 制造商代码 VARCHAR(4)(pk)
  • 描述
  • 生效日期不为空
  • 到期日期不为空

制造商代码 | 描述 | 生效日期 |
福特| 有效期 福特 | 1900 年 1 月 1 日 | 12-31-9999
宝马 | 宝马| 1900 年 1 月 1 日 | 12-31-9999
雪佛兰 | 雪佛兰 | 1900 年 1 月 1 日 | 12-31-9999

制造商类型代码

  • 制造商类型代码 (pk)
  • 描述不为空

制造商类型代码 | 描述
大师| 大师
定制| 风俗

制造商详情

  • 制造商详细信息 ID(pk)
  • 制造商代码 (fk) 不为空
  • 制造商类型代码 (fk) 不为空
  • 客户 ID (fk) 不为空

制造商详细信息 ID | 制造商代码 | 制造商类型代码 | 客户 ID
1 | 宝马| 大师| 1
2 | 宝马| 定制| 1

模型

  • 型号-ID(PK)
  • 制造商详细信息 ID (fk) 不为空
  • 描述不为空

型号-ID | 制造商详细信息 ID | 描述
1 | 1 | M3
1 | 2 | M3降低