SQL表的规范化

时间:2017-03-10 10:40:50

标签: sql normalization

我正在为项目创建一些表,并且意识到许多表具有相同的结构(Id,Name),但是用于不同的事情。我应该在规范化的范围内走多远?我应该将它们全部放在一张桌子上还是将它们分开以便更好地理解?它如何影响性能?

示例1:

TableObjectType(用于日志中的对象类型)

protocol ProtocolA {
    var someProperty: ProtocolB { get }
}

protocol ProtocolB {}
class ConformsToB: ProtocolB {}

class SomeClass: ProtocolA {

    // dummy property to satisfy protocol conformance.
    var someProperty: ProtocolB {
        return actualSomeProperty
    }

    // the *actual* implementation of someProperty.
    var actualSomeProperty: ConformsToB

    init(someProperty: ConformsToB) {
        self.actualSomeProperty = someProperty
    }
}

TableAction(用于日志中的操作类型)

Id  Name
1   User
2   MobileDevice
3   SIMcard

TableStatus(用于设备可以拥有的状态)

Id  Name
1   Create
2   Edit
3   Delete

示例2:

TableConstants

Id  Name
1   Stock
2   Lost
3   Repair
4   Locked

忽略命名,因为我的表有其他名称,但我使用这些来澄清。

对所有常量使用一个表的缺点是,如果我想稍后添加更多,它们实际上不会进入“组”,但另一方面在SQL中我不应该依赖于特定的顺序数据。

2 个答案:

答案 0 :(得分:1)

我认为通常最好将表格分开(它也有助于文档)。在某些特定情况下(您的选择是......),您可以将所有类似的表“合并”为一个(当然,添加其他列,如TAB_TYPE以区分它们):这可以为您提供开发应用程序和减少整体的一些优势表的数量(这对你来说是一个问题) 如果它们都是相对较小的表(记录不多),则应该没有性能问题。

答案 1 :(得分:1)

仅仅因为表格具有与另一个表格相似的结构并不意味着它存储描述相同实体的数据。

有一些明显的理由不参与示例2。

首先,您可能希望将ObjectTypeID列中的值限制为有效对象类型的值。显而易见的方法是创建ObjectType表的外键关系。在TableConstants上创建类似的检查要困难得多(在大多数数据库引擎中,您不能以这种方式使用外键约束)。

其次,它使数据库自我描述 - 正在检查模式的人将理解"对象类型"在您的业务领域中是一个有意义的概念。这对于长期存在的应用程序或具有大型开发团队的应用程序非常重要。

第三,您经常会使用这些引用获得特定的业务逻辑 - 例如," status"通常需要一些逻辑来表示"你不能修改状态为LOCKED"的记录。这种业务逻辑通常需要存储额外的数据属性 - 使用"常量"表

第四 - "常数"必须得到管理。如果您有一个大型模式,很快人们就会开始重复使用常量来反映略有不同的概念。你的"创造" constant可能会应用于存储业务请求的表以及日志事件。这变得几乎无法理解 - 如果业务决定日志事件,请不要参考"创建"但是"写",你的商业交易都开始出错了。

可以做的是使用ENUM(许多数据库引擎支持这个)来建模除了存储名称之外没有太多逻辑的属性。这样可以消除风险1,2和4,但这意味着您的逻辑在数据库模式中编码 - 添加新对象类型是模式更改,而不是数据插入。