对于这个问题,考虑一个使用 Multi-Tenancy 数据库和制造商和型号建模的应用程序。如果我们谈论的是汽车,那么制造商将是福特、雪佛兰、宝马等,而车型将是 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');
模型表
/*
* 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 */
使用这些表格简化 View
/*
* 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;
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
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
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
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
最佳答案
您需要以下表格:
- 制造商代码
- 制造商类型代码
- 制造商详细信息
- 型号代码
- 模型类型代码
- 模型细节
如果您有包含相同数据的表 - 您需要合并它们,并使用 TYPE_CODE 表来区分它们。
回复:制造商和客户 目前,您需要 PK 为 MANUFACTURER-ID 和 CUSTOMER-ID。最好将制造商拆分为制造商代码和制造商详细信息。 MANUFACTURER-CODE 将包含“BMW”、“FORD”等以及自定义。 MANUFACTURER-DETAILS 允许您保留每个客户的详细信息数据,同时允许您为“BMW”/等之类的东西重用代码。模型也是如此。
下一步是为引擎、车轮等定义 TYPE-CODE 表。我将使用名为 MODEL-ATTRIBUTES 的 XREF 表将这些与 MODEL-DETAILS 相关联。 MODEL-ATTRIBUTES 表将包含:
- 型号-详细信息-ID (pk)
- 模型属性类型代码 (pk)
- 属性代码 (pk)
这将允许可选模型属性与适用的 MODEL-DETAILS 记录相关联,而无需不断向 MODEL-DETAILS 表中添加属性。
制造商代码
- 制造商代码 VARCHAR(4) (pk)
- 描述
- 生效日期不为空
- EXPIRY-DATE 不为空
制造商代码 |说明 |生效日期 |有效期
福特 |福特 | 01-01-1900 | 12-31-9999
宝马 |宝马 | 01-01-1900 | 12-31-9999
雪佛兰 |雪佛兰 | 01-01-1900 | 12-31-9999
制造商类型代码
- 制造商类型代码 (pk)
- DESCRIPTION 不为空
制造商类型代码 |描述
硕士 |大师
自定义 |自定义
制造商详细信息
- 制造商详细信息 ID (pk)
- 制造商代码 (fk) 不为空
- MANUFACTURER-TYPE-CODE (fk) 不为空
- 客户 ID (fk) 不为空
制造商详细信息 ID |制造商代码 |制造商类型代码 |客户编号
1 |宝马 |硕士 | 1
2 |宝马 |自定义 | 1
型号
- 型号 ID (pk)
- MANUFACTURER-DETAILS-ID (fk) 不为空
- DESCRIPTION 不为空
型号编号 |制造商详细信息 ID |描述
1 | 1 | M3
1 | 2 | M3降低
关于sql - 每个客户有选择地覆盖主数据的数据库结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1146092/