【问题标题】:Should this column belong to the primary key or not and it could be null?该列是否应该属于主键并且可以为空?
【发布时间】:2021-02-24 15:07:36
【问题描述】:

我有任务在某些项目中执行某些任务,并且同一项目的相同任务可以在不同的时期完成(每 1 天、2 天……等)。另外这个任务需要一些材料,这取决于任务,但有些任务在某些时期不需要材料,在另一些情况下它需要。

所以我的第一个想法是拥有这张桌子:

TaskOfItemsOnPeriodWithMaterials
{
    IDItem;
    IDTask;
    IDPeriod;
    IDMaterial;
    AMountOfMaterial;
}

在这种情况下,主键是IDTiem, IDTask, IDPeriod, IDMaterial

但是如果IDMaterial是key的一部分,它不能为null,所以我不能在没有材料的一个时期内有任务,因为它是需要的。

所以我认为如果IDMaterial 必须是主键,因为实际上它是唯一值的条件,也许我需要另一个表,类似这样:

TaskOfItemsOnPeriod
{
    IDItem;
    IDTask;
    IDPeriod;
}

所以我不得不维护两个表。

但我想知道是否会有更好的解决方案。

谢谢。

【问题讨论】:

  • 表格有,而不是字段。 (日期有年份字段、月份字段和日期字段。)
  • "在这种情况下,主键是 IDTiem、IDTask、IDPeriod、IDMaterial。"一张表可能只有一个主键。您是说要连接字段中的值以在新字段中创建主键,还是要决定将其中哪些用作主键?如果我理解正确,您可能想要创建一个连接 IDTask 和 IDItem 的主键,因为它看起来是非唯一的并且材料可以为空。这将允许您只有一个表,尽管添加了另一个字段(列)。
  • 对,我的意思是我在考虑一个主键,即四列,IDItem、IDTask、IDPeriod 和 IDMaterial。我将 IDPeriod 视为主键的一部分,因为一个项目的任务可以分为多个时期,并且每个时期可能需要不同的材料。这就是为什么一开始我认为四列必须是主键的一部分。
  • @Greg 一个表可以有多个列作为主键,一个composite key
  • 任务需要物品和材料吗?还是任务需要物品/材料对?例如,一项任务是否需要每天 5 只羊、10 根羊毛、剪毛机和周末的锯木厂?或者一个任务每天需要 5 只羊用剪毛机,再加上 10 只羊毛在周末用锯木厂?

标签: sql database-design


【解决方案1】:

让我们更正式地说明一下这个问题。

  • some task in some items”一个任务有很多项目,我假设一个项目可以有很多任务:多对多
    • "同一个项目,同一个任务,可以分期完成 (每 1 天、2 天……等)”任务只能在特定时间段内使用该项目
  • 我需要一些材料来完成这个[任务]”一个任务有很多数量的材料,大概一个材料可以有很多任务:多对多
    • 一项任务需要大量材料

我们的数据表是...

  • 任务
  • 项目
  • 材料

这些表格的细节无关紧要。我们只关心它们有一个主键,假设它们有一个名称以用于示例目的。

我们需要两个多对多连接表。一种将项目与任务联系起来,一种将材料与任务联系起来。这些不是纯粹的连接表,它们有额外的数据。

  • task_items
    • 可以完成的时间段
  • task_materials
    • 任务所需的材料数量
create task_items (
  task_id bigint not null references tasks(id),
  item_id bigint not null reference items(id),
  -- How the period should be stored is another question
  -- and depends on the database.
  period text not null
);

create task_materials (
  task_id bigint not null references tasks(id),
  material_id bigint not null references materials(id),
  quantity integer not null check(quantity > 0)
);

应该这样做。将项目和材料添加到任务...

-- Task 10 needs 5 of material 20 and 3 of material 40.
insert into task_materials (task_id, material_id, quantity) values
  (10, 20, 5),
  (10, 40, 3);

-- Task 10 needs item 5 every 2 days, and item 10 every day.
insert into task_items (task_id, item_id, period) values
  (10, 5, '2 days'),
  (10, 10, '1 day');

例如,查找任务所需的所有材料和数量...

select t.name, m.name, tm.quantity
from task_materials tm
join materials on m.material_id = tm.material_id
join tasks on t.task_id = tm.task_id
where tm.task_id = 1234

【讨论】:

  • 认为提问者的意思是,在某些时期,该任务需要材料,而在其他时期,该任务不需要该材料。
  • @NevilleKuyt 目前还不清楚。它可能都围绕着时间段?我已经要求澄清。
  • @NevilleKuyt 是对的。我的意思是,在某些时期,相同的任务可能需要不同的材料。
  • @ÁlvaroGarcía 我发布了一些 cmets,要求提供一个可靠的示例。如果你回答他们,我可以再试一次。
猜你喜欢
  • 2020-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-21
  • 1970-01-01
相关资源
最近更新 更多