我想用新实体Sale
打破SalesMan
和Customer
之间的多对多关系。
我想使用 idSalesMan
和 idCustomer
作为 Sale
中的主键,但是 SalesMan
有一个外键在 Sale
实体中。
我是否需要将所有 3 个外键用作主键,或者 idSalesMan
和 idCustomer
就足够了吗?
下面是脚本的样子(使用 Postgres):
CREATE TABLE Company(
idCompany SERIAL PRIMARY KEY,
name VARCHAR(45) NOT NULL
);
CREATE TABLE SalesMan(
idSalesMan SERIAL PRIMARY KEY,
name VARCHAR(45),
wage DOUBLE NOT NULL,
Company_idCompany INT REFERENCES Company ON DELETE CASCADE
);
CREATE TABLE Customer(
idCustomer SERIAL PRIMARY KEY,
name VARCHAR(45) NOT NULL
);
CREATE TABLE Sale(
SalesMan_idSalesMan INT REFERENCES SalesMan ON DELETE CASCADE,
SalesMan_Company_idCompany INT REFERENCES Company ON DELETE CASCADE,
Customer_idCustomer INT REFERENCES Customer ON DELETE CASCADE,
PRIMARY KEY (SalesMan_idSalesMan, Customer_idCustomer
/*,SalesMan_Company_idCompany?*/)
);
最佳答案
要回答图 block 中的问题:否,不一定。
只有当 FK 列的组合需要 UNIQUE
和 NOT NULL
时,这样的 PK 才有意义。两者都不是必须的。事实上,在这个模型中强制执行唯一性看起来很奇怪。不允许客户从同一个销售员那里购买两次? (涉及同一家公司?)
您将有额外的列来使 Sale
中的每一行都是唯一的。 时间戳
浮现在脑海中。你会有那个,但它通常不会使销售独一无二。两次购买可能同时发生。如果没有可靠的自然键,请使用代理 PK,例如 serial
或 IDENTITY
列。
我会在任何 情况下这样做,即使这组 FK 列恰好被定义为 UNIQUE
和 NOT空
。我会在适用的情况下创建UNIQUE
约束或索引另外(和NOT NULL
约束)。 (或者在大多数情况下至少是性能的普通索引。)也许除了非常简单的情况外,只有两个小的 FK 列可以形成 PK,并且表本身不被 FK 约束引用并且以后不太可能更改。对于任何其他方面,代理 PK 更简单、更快、更可靠,并且使以后的更改更容易。
另外,喜欢Mureinik explained , FK 列 SalesMan_Company_idCompany
通常是多余的,应该删除:它由销售人员决定。 除非您的模型允许客户和销售人员之间以某种方式涉及独立公司的销售。
我还会重新考虑显示的命名约定。更多:
关于database - 是否有必要将所有 3 个外键用作关联实体中的主键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50886822/