重构数据库,我应该使用代理键



我继承了一个Access数据库,我正在迁移到SQL Server。在数据库中有很多标记或分类列。例如,订单表可能有一个状态属性,供应商可能有一个评级属性。它们大多数都没有真正的业务逻辑,它们本身不是实体,它们都只是允许用户进行标记和搜索的描述符。

一方面,我认为这些描述符应该放在它们自己的表中,并使用外键引用。然后在我的应用程序代码中,我可以使用匹配代理id的枚举。为什么?因为我可以很容易地添加它们,改变它们的值,也许可以节省一些空间

Order { OrderId int, CustomerId int, StatusId int}
Status { StatusId int, Name varchar(50)} 

另一方面,因为这些属性中的许多永远不会改变,永远不会被添加,而且我还有一堆其他的事情要做,所以我认为我应该离开它。

Order{OrderId int, CustomerId int, Status varchar(50)}

上面的第一个选项总是应该这样做吗?第二种选择可以接受吗?我认为保留它的唯一缺点是表会稍微大一些,并且字符串比较可能不如int比较快。

如果您需要更多地控制在"Status"列中找到的值,您还可以从Order中插入不同的值。状态到另一个表中,并设置对它的外键引用。按照你描述表格的方式…

Order{OrderId int, CustomerId int, Status varchar(50)}
Status {Name varchar(50)} 

我会选择比"Name"更具描述性的内容作为该列。级联更新还是删除取决于应用程序。当你在SQL Server上,你可以用SQL GRANT和REVOKE语句控制谁可以更新"状态"表。(你也可以在Access中这样做,但你似乎正在远离它。)

要从这个表中获得有意义的数据需要两个连接而不是三个。想想你是否需要50个字符。(访问权限默认为50。大多数人从不改变它。

现在,为了回答你的问题,上面的第一个选项并不是总是应该做的方式。ID号总是会增加所需的连接数量,并且仍然需要对自然键使用UNIQUE约束。把身份证号用于美国州代码、邮政编码等是没有任何意义的。第二种选择通常对我来说是不可接受的;我会通常引用另一个表与外键,就像我在这个答案的顶部所做的。

最新更新