将许多子表关联到父表

时间:2012-01-05 04:42:32

标签: sql-server database database-design

我会尽力将其列入文本中。从本质上讲,我们有一个应用程序可以跟踪用户执行的操作。每个操作都有自己的表,因为每个操作都有不同的参数需要存储。这使我们可以轻松地存储这些额外的属性,并在多个或单个用户的操作上运行分析。除了用户执行这些操作之外,这些操作并不真正相互关联。

示例:

  • ActionTableA Id | UserId | AttributeA | AttributeB
  • ActionTableB Id | UserId | AttributeC | AttributeD | AttributeE
  • ActionTableC Id | UserId | AttributeF

接下来,我们需要为用户执行的每个操作分配一个值,并保持这些值的运行总计。

实施例: ValueTable: Id | UserId |价值| ActionType | ActionId

将值表中的值与实际执行的操作相关联的最佳方法是什么?我们知道动作类型(A,B,C) - 但是从SQL设计的角度来看,我看不到在ActionsTable中的动作的值与实际动作本身之间建立索引关系的好方法。唯一有意义的是将ValueTable修改为以下内容:

ValueTable

Id | UserId |价值| ActionType | ActionAId(FK Nullable)| ActionBId(FK Nullable)| ActionCId(FK Nullable)

但是我遇到的问题是3个actionTableId列中只有一个会有一个值,其余的都是Null。此外,随着动作类型的添加,值表中的列也将如此。最后,为了以编程方式查找数据,我要么a)必须检查ActionType以获取Id的相应列,或b)扫描行并选择非null actionId。

是否有更好的方式/设计,或者这只是“这个特定问题的方式”。

修改

附件是上述设置的图表:

enter image description here

对于清晰度问题感到抱歉,输入SQL问题始终具有挑战性。所以我认为你的评论给了我一些想法......我可以拥有一个基本上具有自动生成值的SystemActionId表

SystemActions :Id |型

然后,每个ActionTable都会有一个额外的FK到SystemAction表。最后,在ValueTable中 - 也将它与SystemActions表相关联。这将允许我们将值与特定操作联系起来。我需要将操作表连接到系统操作表

JOIN (((SystemActions.Id = ActionTableA.Id) JOIN (SystemActions.Id = ActionTableB.Id)) JOIN (SystemActions.Id = ActionTableC.Id)

糟糕的快速SQL语法

这是你在下面的答案中提到的吗?可能看起来像什么的快照:enter image description here

5 个答案:

答案 0 :(得分:1)

您的问题有点不清楚,但看起来您应该在每个操作表中都有一个(非规范化的)值列,或者在值表中有一个由每个单独的操作表键入的人工键。

答案 1 :(得分:1)

你基本上有一个超类型/子类型结构,或一个独占弧。所有操作共有的属性将“向上”冒泡到超类型(表“操作”)中。每个子类型唯一的列“向下”冒泡到不同的子类型中。

create temp table actions (
  action_id integer not null,
  action_type char(1) not null check (action_type in ('a', 'b', 'c')),
  user_id integer not null, -- references users, not shown.
  primary key (action_id),
  -- Required for data integrity. See below.
  unique (action_id, action_type)
);

create temp table ActionTableA (
  action_id integer primary key,
  -- default and check constraint guarantee that only an 'a' row goes
  -- in this table.
  action_type char(1) not null default 'a' check (action_type = 'a'),
  -- FK guarantees that this row matches only an 'a' row in actions.
  -- To make this work, you need a UNIQUE constraint on these two columns
  -- in the table "actions".
  foreign key (action_id, action_type) 
    references actions (action_id, action_type),
  attributeA char(1) not null,
  attributeB char(1) not null
);

-- ActionTableB and ActionTableC are similar.

create temp table ValueTable (
  action_id integer primary key,
  action_type char(1) not null,
  -- Since this applies to all actions, FK should reference the supertype,
  -- which is the table "actions". You can reference either action_id alone, 
  -- which has a PRIMARY KEY constraint, or the pair {action_id, action_type},
  -- which has a UNIQUE constraint. Using the pair makes some kinds of 
  -- accounting queries easier and faster.
  foreign key (action_id, action_type) 
    references actions (action_id, action_type),
  value integer not null default 0 check (value >= 0)
);

要解决此问题,请构建可将超类型连接到每个子类型的可更新视图,并让所有用户使用视图而不是基表。

答案 2 :(得分:0)

说实话,我只会有一张表来表示行动。有多个表是否有原因(除了非规范化)?特别是当它会增加业务逻辑的复杂性时?

属性列在架构的上下文中是否重要?你能将它压缩成对象存储列“属性”吗?

Actions: actionID, type, attributes

答案 3 :(得分:0)

我认为您需要类似于Audit Trail的东西。我们可以有一个简单的设计,以便所有的操作都可以在一张单表中捕获吗?

enter image description here

答案 4 :(得分:0)

如果您希望它的工作方式是每次用户执行操作A,您在表ActionTableA中插入一个新行,在ValueTable中插入一行,并将它们都链接,为什么不每个操作表中都有一个值列?仅当您希望每次用户执行操作时插入新行而不想在用户再次执行相同操作时更新值时,此操作才有效。如果可以将值存储在列中,则为值提供单独的表似乎过于复杂。另一方面,如果“值”是一组不同的数据(或者如果你想在一个地方拥有所有值)那么你确实需要一个额外的表,但我仍然有一个指向动作的外键列表到值表。