【问题标题】:How can I require a field to be either free or paid but not both?我怎样才能要求一个字段是免费的或付费的,但不能两者兼而有之?
【发布时间】:2022-01-05 13:42:33
【问题描述】:

我有免费和付费的主题桌。 免费主题有下载链接 付费主题有购买链接和价格。

这是一个图形格式的数据库模式:

一个主题不能同时收费和免费。如何防止两个表(FreeThemes、PaidThemes)同时拥有一个主题的数据?

【问题讨论】:

  • 看起来规范化已经走得太远了你坚持这个设计吗?如果是这样,请使用免费主题和付费主题上的插入和删除触发器进行验证
  • 我正在尝试遵循规范化规则,但我认为我有点夸张。你觉得这个设计好还是需要重新设计?
  • 这样说,如果你必须通过箍,那么它可能太远了,我不知道你通过分成 3 个表来节省什么。我会考虑有一张桌子和一列来表明它的主题是免费的还是付费的。这样一来,您只需花费很少的代价就可以避免加入复杂性的问题。-当然,如果您的架构针对问题进行了简化,则此路线可能不合适。
  • 这能回答你的问题吗? How can you represent inheritance in a database?

标签: mysql database database-design


【解决方案1】:

这是Class table inheritance. 的一个示例,这是一个完全有效的设计选择(我不同意这是“规范化走得太远”)——它是一种解决关系模型局限性的方法。

另一个限制是,没有干净、原生的方式来声明性地声明您需要的业务规则。

有几种常见的方法可以解决这个问题。

首先是将责任委托给应用层。如果有单个应用程序/服务连接到数据库,这并不可怕 - 特别是如果您可以将逻辑包装在单元测试等中。

第二个是将逻辑嵌入到触发器中。这使您即使在许多应用程序使用数据库的情况下也能保证此业务规则,但是当您的业务逻辑发生变化时(例如,如果您需要添加新的子类),您必须更改触发器。

最后一个选项是在主题表中添加一个“类型指示符”,并使用该标志而不是子类表中存在的一行来确定主题是免费的还是付费的。同样,不是很优雅,需要客户端应用程序遵守该标志,但它确实巧妙地表达了业务意图。

【讨论】:

    【解决方案2】:

    关于子类型的一句话。实现子类型约束的正确方法是使用断言 (CREATE ASSERTION),但它在主要数据库中仍然不可用。我改用FKs,与所有其他替代方法一样,它并不完美。人们争论很多,关于 SO 和 SE-DBA,什么更好。我也鼓励您检查其​​他方法。

    -- Theme THM, of theme-type THM_TYP exists.
    --
    theme {THM, THM_TYP, -- other_common_attributes}
       PK {THM}
       SK {THM, THM_TYP}
    
    CHECK THM_TYP in ('F', 'P')
    
    -- Free theme THM (of theme-type 'F') exists.
    --
    free_theme {THM, THM_TYP,
               -- other attributes specific to free}
            
    PK {THM}
    
    FK {THM, THM_TYP} REFERENCES theme {THM, THM_TYP}
    
    CHECK (THM_TYP = 'F')
    
    -- Paid theme THM (of theme-type 'P') exists.
    --
    paid_theme {THM, THM_TYP,
               -- other attributes specific to paid}
    
    PK {THM}
    
    FK {THM, THM_TYP} REFERENCES theme {THM, THM_TYP}
    
    CHECK (THM_TYP = 'P')
    

    注意:

    All attributes (columns) NOT NULL
    
    
    PK = Primary Key
    AK = Alternate Key   (Unique)
    SK = Proper Superkey (Unique)
    FK = Foreign Key
    

    遵循正式的规范化规则不会让您得到这个解决方案。 free_themepaid_theme 表都有 FD {} --> {THM_TYP};换句话说,属性 THM_TYP 不依赖于 PK {THM},因此这些表在 2NF 中

    在这种情况下,FKCHECK 约束可防止异常和逻辑错误——这是规范化的首要目标。

    如果您对不属于 2NF 的表有疑问,可以通过以下方式考虑:

    1. 确保 free_themepaid_theme 表处于高 NF (5NF) 状态,没有 THM_TYP 属性。
    2. 添加THM_TYP以便处理问题,了解妥协。
    3. 请记住,问题的根本原因是当前 SQL 实现中缺少所需的跨表约束(断言)。

    【讨论】:

      【解决方案3】:

      亲吻。一桌两用 -- 设价格为 0.00 表示免费。

      (或者NULL 可以表示“免费”,但我看不出有什么优势。)

      【讨论】:

        【解决方案4】:

        主题类型中的新字段是或否(复选框)

        如果是,则“免费”;其他情况“付费”

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-04-05
          • 2017-07-27
          • 2011-06-05
          • 1970-01-01
          • 2023-04-08
          • 2015-04-03
          • 1970-01-01
          相关资源
          最近更新 更多