数据库架构一致性问题

时间:2011-04-30 23:53:21

标签: sql-server sql-server-2008 database-design data-modeling

我的部分数据库架构涉及实体:

Jobs
Agencies
Agents
and relation JobAgent
  • 每个工作都有一个属于
  • 的代理商
  • 每个代理商属于一个代理商
  • 每个Job都有0-n个座席

数据库将是SQL Server 2008

这是我的架构:

enter image description here

我的问题是Jobs.agencyid在通过JobAgent关联时必须始终等于Agents.agencyid。 如果要将Jobs.agencyid更新为新的代理商,则代理商将属于与该职位不同的代理商。

重新设计架构以避免依赖触发器或应用程序代码来确保这种一致性的最佳方法是什么?

4 个答案:

答案 0 :(得分:1)

  • agency_id(pk)

工作

  • job_id(pk)
  • agency_id(fk to AGENCIES.agency_id)

  • agent_id(pk)
  • agency_id(fk to AGENCIES.agency_id)

JOBAGENT

  • JOB_ID
    • fk to JOBS.job_id
  • AGENT_ID
    • fk to AGENTS.agent_id
  • agency_id
    • fk to JOB.agency_id
    • fk to AGENTS.agency_id

您可以为列定义多个外键约束 - 它只是意味着JOBAGENT中的值必须满足允许的BOTH外键约束。但是,如果您想要将作业更新到其他代理商,那么您将获得乐趣......;)SQL Server支持复合外键:http://msdn.microsoft.com/en-us/library/ms175464.aspx

有关更新的更新

您有两种选择 -

  • 手动执行,因为ON UPDATE CASCADE等不会在不使用触发器的情况下处理代理和代理更新
  • 在JOB中有一个状态列,因此您可以取消作业以使用新的支持记录(代理,作业代理等)重新创建作业。如果您愿意,可以根据工作状态自动进一步清理

答案 1 :(得分:1)

问题是如果一个工作从一个代理转移到另一个代理(如你所说,如果要更新Jobs.agencyid ......)那么JobAgent中的相应记录就变得毫无意义了:那些代理不能附加到不再与其代理商合作的作业,因此应删除将其连接到作业的JobAgent记录...

强制执行此操作的一种方法是添加 JobAgent.agencyid 字段,并将其设置为 Jobs.agencyid 上的外键,并强制使用ON UPDATE RESTRICT(手动) )在Jobs.agencyid可以更改之前删除相关的JobAgent记录。


编辑:另一个我没有考虑过的问题是,当您第一次将作业与代理关联时(即创建新的JobAgent记录),您需要确保它们都属于对于同一个机构......为此,我认为OMG's solution效果最好 - 我很乐意接受更好的答案。

OMG还提出了如何处理更新的问题:你可以

  1. 更改Jobs.agencyid字段并删除(手动)所有关联的JobAgent记录:在这种情况下,旧代理不再适用于此作业,您可以指派新代理商处理某人。

  2. 更改Jobs.agencyid字段,也更改所有关联的JobAgent记录(即所有这些代理随作业移动到新代理商) - 但这是very messy,因为这些代理商也会与仍在原代理机构的其他工作相关联。

  3. 正如OMG建议的那样,创建一个新的Jobs记录并将旧记录标记为已不存在(以后删除)。

  4. 如上所述,但保留已解散的乔布斯记录以保留历史信息。

  5. 您是选择3还是4取决于您的系统的用途:您是否只想维持who-has-which-jobs的当前状态?或者您是否需要保留某种历史记录,例如,如果工作中附有计费记录......该信息需要与原始代理机构保持关联(但这超出了原始问题的范围)。

答案 2 :(得分:0)

您可以将ON UPDATE CASCADE与外键一起使用。见Wikipedia Page。 或者,如果agencyid是您期望可变的内容,则可以为其设置唯一约束,并为代理ID(例如,自动增量列)使用其他无意义字段。

答案 3 :(得分:0)

以下方案是否回答了您的问题?

    Jobs      Agents     Agencies
      ^          ^          ^
      |          |          |
       \         |         /
        \        |        /
           AgentiatedJob

通常,我为每个表都有一个单字段主键,因为它更容易匹配表上的注册表并在下表中引用它。因此,遵循这种方法,AgientiatedJob至少会有以下字段:

  • AgentiatedJobId
  • 的JobId
  • AGENTID
  • AgencyId