规范化具有重复行和多对多关系的表

时间:2014-08-11 10:42:56

标签: sql sql-server database-normalization

我正在为会计系统设计数据库,目前正在使用费用表。

根据IRS规则,每当您更新任何会计表中的行时,您需要通过否定其值来取消现有行,并使用修改后的信息创建一个新行,如下所示:

  1. 将行的状态标志设置为“已修改”
  2. 创建此行的相同副本,并取消所有Money字段,以使两行的总和为0
  3. 使用修改后的数据
  4. 创建第3行,与第一行相同

    每个费用都有一个名为ID的标识字段用于内部标识,还有一个ExpenseID字段,用于标识用户的事务。两者不能相同,因为

    1. 如果修改了事务并且其行重复,则可以重复两次ExpenseID。
    2. ExpenseID必须是连续的,并且永远不会有间隙,而如果回滚事务并且不重新接种该身份,则身份字段可以跳过数字。
    3. 一般来说,我认为主键应该没有任何商业意义。
    4. 我的问题是,还有其他表用于将这些费用与我们系统中的其他对象的多对多链接相关联。例如:每个费用可以链接到文档,文件夹,用户等。

      所以它看起来像这样:

      create table Expenses (
          ID int not null identity(1,1),
          ExpenseID int not null,
          Amount Money not null,
          Status tinyint not null,
          [...]
      )
      
      create table Expenses_Users (
          ExpenseID int not null,
          UserID int not null
      )
      
      alter table Expenses_Users add constraint FK_Expenses_Users_Expenses
      foreign key (ExpenseID) references Expenses (ID)
      
      alter table Expenses_Users add constraint FK_Expenses_Users_Users
      foreign key (UserID) references Users (ID)
      

      现在,由于IRS指南,我不仅要复制Expenses表中的行,还要复制Expenses_Users中的行,以及将Expenses链接到其他表的任何其他表。

      我有两个关于如何解决这个问题的想法:

      选项一:规范化费用如下:

      create table Expenses (
          ID int not null identity(1,1),
          ExpenseID int not null,
          Status tinyint not null,
          [...]
      )
      
      create table ExpensesNormalized (
          ExpenseID int not null,
          Amount Money not null
      )
      
      alter table ExpensesNormalized add constraint FK_ExpensesNormalized_Expenses
      foreign key (ExpenseID) references Expenses(ExpenseID)
      

      这意味着我只需要将外部表链接到费用,而不是ExpensesNormalized。此外,在更新费用时,我只会复制和否定ExpensesNormalized中的数据,这意味着我在费用表中的冗余数据要少得多。

      但是,每次从Expenses中选择时,我都必须使用JOIN子句。我担心会因此受到影响。

      选项二:使用我现在使用的相同表格,但将字段Expenses_Users.ExpenseID指向字段Expenses.ExpenseID。这意味着我不必复制任何外部对象,因为它们会指向ExpenseID,这可能会多次出现。

      但是,这不是真正的外键,因为SQL Server不允许外键到非唯一字段,所以我必须在触发器中实现外键逻辑。

      我很难决定这两个选项。任何反馈都将不胜感激。

0 个答案:

没有答案