【问题标题】:Make relation between five tables to one table in SQL Server that do not refuse database normalization在不拒绝数据库规范化的 SQL Server 中将五张表与一张表建立关系
【发布时间】:2018-04-07 11:08:12
【问题描述】:

我有一些名称为联系人、关注、任务、工单、帐户和...的表格 上面的每一个表,都应该和 Notifications 表有关系。

现在我在 SQL 中为 Notifications 表使用这种结构来创建它们之间的关系:

Id, ContactId, FollowId, TaskId, TicketId, AccountId, Text

Id 是主键,ContactIdFollowIdTaskIdTicketIdAccountId 应该是外键。

每次向该表中添加一条记录时,该外键列表中只有一列获得了值,如下所示:

Id  ContactId   FollowId    TaskId  TicketId    AccountId   Text
1   null        null        null    null        2           notification test 1
2   null        null        null    12          null        notification test 2
3   null        null        null    11          null        notification test 3
4   5           null        null    null        null        notification test 4
5   null        1           null    null        null        notification test 5
6   null        null        null    null        3           notification test 6
7   null        null        null    null        43          notification test 7

这是一个不拒绝databBase规范化的优秀架构师吗?

【问题讨论】:

  • 您的 fkeys 似乎指向错误的方向..?
  • 为什么不在每个表中添加notificationID 外键呢?从那里您可以监控每个表及其通知。

标签: sql sql-server database database-design


【解决方案1】:

您创建的结构是非规范化结构,不适合 OLTP 环境。

下面是理想的归一化结构

Notifications Contacts
Notifications Follows
Notifications Tasks
Notifications Tickets
Notifications Accounts

【讨论】:

    【解决方案2】:

    这是一个很好的解决方案吗?嗯,不是真的。但是对于与一堆其他实体相关的实体(例如notations),SQL 没有很好的解决方案。

    此特定解决方案的优点是您可以声明外键关系。它的缺点是添加新的实体类型需要重组表,并且每个NULL 值都会占用空间。所以,它不是特别可扩展的。

    没有完美的解决方案。如果您愿意放弃外键关系,您可以这样做:

    create table notifications (
        notificationId int identity(1, 1) primary key,
        notificationType varchar(32),
        relatedId int,
        check notificationType in ('contact', . . .)
    );
    

    很遗憾,SQL Server 没有过滤外键关系。你可以这样做:

    create table contacts (
        contactId int identity(1, 1) primary key,
        . . .
    );
    
    create table n (
          id int identity(1, 1),
          relatedId int,
          notificationType varchar(32),
          contactId as (case when type = 'contact' then relatedId end) persisted,
          foreign key (contactId) references contacts(contactId)
    );
    

    这几乎可以满足您的需求。问题是contactId 需要持久化才能在外键关系中使用——并且持久化的计算列仍然占用空间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-05
      • 2016-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多