【问题标题】:How to address a multiple purpose column in sql?如何处理sql中的多用途列?
【发布时间】:2018-09-28 20:08:01
【问题描述】:

场景

我需要设计一个来自多个来源和目的地的设备运动。我有以下示例表:

CREATE TABLE Area{
    Id INT,
    Name VARCHAR(50),
    //some other fields
}

CREATE TABLE Stowage{
    Id Int,
    Name VARCHAR(50),
    //some other fields
}

CREATE TABLE Movement{
    OriginId INT,
    DestinationId INT,
}

但我需要一些动作,例如:

  1. 原点:区域; 目的地:地区
  2. 原点:区域; 目的地:装载
  3. 原产地:积载; 目的地:地区
  4. 原产地:积载; 目的地:装载

但我只有两列,每列需要多个外键。

考虑可能的解决方案

  1. 创建 MovementArea、MovementStowage、MovementStowageArea 表并创建其适当的外键。
  2. 不要为 OriginId 和 DestinationId 列创建外键,并根据需要进行填充。

最后一个问题

是否有另一种方法可以在 sql 中解决这个问题,或者提供的哪种解决方案最适合这种情况?

【问题讨论】:

  • 为什么 area 和 stowage 需要分开表?难道你不能将它们存储在同一个表中,使用IDNameType(面积/积载)列来避免这个问题吗?
  • @APH 可能是一个解决方案,但 Stowage 和 Area 有不同的目的,不同的列(我没有在示例中添加,只是发表评论)并且来自不同的来源
  • 嗨。事物是其他事物的子类型。因此 SQL/数据库子类型/继承。反模式是 2/many/multiple FK 到 many/multiple/2 表。这是一个常见问题解答。请始终在谷歌上搜索您的问题/问题/目标的许多清晰、简洁和特定的版本/措辞,带和不带您的特定字符串/名称,并阅读许多答案。将您发现的相关关键字添加到搜索中。如果您没有找到答案,请发布,使用 1 个变体搜索作为标签的标题和关键字。请参阅向下投票箭头鼠标悬停文本。如果您确实有要发布的非重复代码问题,请阅读并通过minimal reproducible example 采取行动。
  • PS FK 是指列列表的子行值必须出现在其他地方。因此,您不需要“每列需要多个外键”。你有一些让你想起 FK 的东西。在这里,您需要多个列,其中每个列是 FK,只有一个是非 NULL,或者一个列是 FK,引用包含第一种情况下引用列的 UNION 的列。

标签: sql database foreign-keys relational-database


【解决方案1】:

棘手。你有 4 个外键,所以我会 [自然] 创建 4 个外键列,如下所示:

create table movement (

  origin_area int,
  origin_stowage int,
  dest_area int,
  dest_stowage int,

  constraint fk1 foreign key origin_area references area (id),
  constraint fk2 foreign key origin_stowage references stowage (id),
  constraint fk3 foreign key dest_area references area (id),
  constraint fk4 foreign key dest_stowage references stowage (id),

  constraint chk_fk1 check (origin_area is null and origin_stowage is not null
                         or origin_area is not null and origin_stowage is null),
  constraint chk_fk2 check (dest_area is null and dest_stowage is not null
                         or dest_area is not null and dest_stowage is null)
);

现在,如您所见:

  • 有 4 个可为空的 FK 列。
  • 每个外键列都有其对应的外键约束。
  • 另外,origin_areaorigin_stowage 是互斥的。其中一个始终为空,而另一个指向另一个表。这是由 constriaint chk_fk1 强制执行的。
  • dest_areadest_stowage 也是如此。由chk_fk2 强制执行。

【讨论】:

  • 我认为这种方式是解决这个问题最灵活的方法
【解决方案2】:

我的第一个想法是这样的:

Create Table MovementEndpoint
(
    ID Int
    , Name Varchar(50)
    , EndpointType Int              -- Area, Stowage, etc
    , EndpointDetailID Int          -- FK to Area, Stowage, etc
)

现在您的移动只是在端点之间进行,而 MovementEndpoint 记录可让您根据需要到达区域或装载记录。查询逻辑仍然会有些棘手,但不会超出您最初设计的要求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多