规范化模板>实例化模型中的外键问题

时间:2011-06-15 02:56:10

标签: database-design foreign-keys

首先,我的平台是IBM i。这意味着我不习惯普通/通用术语,所以可能会稍微滥用它们。

我正在构建一个数据库设计,它定义了“任务”(动作模板)和“作业”,它们是任务的实例化。

任务在TASKS表中定义,并具有主键TASK_ID。还有另一个表TASK_PARMS来定义任务所需参数的属性。它有一个TASK_ID和PARM_SEQ的复合主键,用于定义参数的顺序。在TASK_PARMS和TASKS之间的TASK_ID上将有一个外键。然后,这些是一个如何执行任务的模板(有更多属性字段来实际定义某些操作,但它们与此问题无关)。示例表格值如下。

 TASKS                      TASK_PARMS
+---------+-----------+    +---------+----------+------------+
| TASK_ID | ATTRIBUTE |    | TASK_ID | PARM SEQ | ATTRIBUTES |
+---------+-----------+    +---------+----------+------------+
| FOO     | PGM_A     |    | FOO     |       10 | ALPHA10    |
+---------+-----------+    | FOO     |       20 | DEC5,0     |
                           +---------+----------+------------+

当我想执行任务时,我实例化一个工作。 JOBS表具有JOB_ID的主键,然后需要定义正在遵循的任务模板。所以它有一个TASKS主键TASK_ID的外键。由于工作由(在概念上,是一个副本)单个任务组成,从标准化的角度来看,这似乎是正确的。

有一个JOB_PARMS表,用于保存此特定作业的实际参数值。当然,它具有JOBS表的JOB_ID外键,但它必须与TASK_PARMS中的序列号具有精确的关系。

 JOBS                      JOB_PARMS
+--------+-----------+    +---------+----------+-----------+
| JOB_ID | TASK_ID   |    | JOB_ID | PARM SEQ | VALUE      |
+---------+----------+    +--------+----------+------------+
|     99 | FOO       |    |     99 |       10 | XY1000AA   |
+--------+-----------+    |     99 |       20 | 2048       |
                          +--------+----------+------------+

这就是我的问题所在。我无法使JOB_PARMS中的序列字段成为TASK_PARMS的外键,因为JOB_PARMS中不存在TASK_ID。

这表明JOB_PARMS中必须存在TASK_ID,以允许外键关系的完整复合键返回TASK_PARMS。但是,由于作业实际上只是一个任务的实例化,JOB_PARMS中的TASK_ID字段永远不会更改为单个JOB_ID值。这似乎打破了正常化。

我觉得我在这里遗漏了一些东西。我可以将TASK_ID粘贴在JOB_PARMS文件中并继续使用它,但我对所有这一切的感觉都想知道我哪里出错了。

1 个答案:

答案 0 :(得分:0)

我认为你原版TASK_IDJOB_PARAMS没有任何问题。

然而,如果它看起来太混乱,你可以尝试这个。创建新作业时,每个任务(1,2,3 ..)的TaskSequenceNo增量。 Job_ID是可选的 - 如果存在,则unique not null

enter image description here

JobParams有两个FK约束,类似(可能需要调整语法):

alter table JobParams
  add constraint fk1_jp foreign key   (TaskId, TaskSequenceNo)
                        references Job(TaskId, TaskSequenceNo)

, add constraint fk2_jp foreign key   (TaskId, Param_Seq)
                 references TaskParams(TaskId, Param_Seq)
;