在SQL Server中将五个表与一个表之间的关系设置为不拒绝数据库规范化

时间:2018-04-07 11:08:13

标签: sql sql-server database database-design

我有一些名称为联系人,关注,任务,门票,帐户和...的表格 上述每个表都应与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中的规范化吗?

2 个答案:

答案 0 :(得分:1)

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

以下是理想的规范化结构

Notifications Contacts
Notifications Follows
Notifications Tasks
Notifications Tickets
Notifications Accounts

答案 1 :(得分:0)

这是一个很好的解决方案吗?好吧,不是真的。但是SQL并没有为与其他实体相关的实体(例如notations)提供一个很好的解决方案。

此特定解决方案的优点是您可以声明外键关系。它的缺点是添加新的实体类型需要重组表,并且每个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才能在外键关系中使用 - 并且持久化的计算列仍占用空间。

相关问题