【问题标题】:Is it bad practice to use default values in a database? [closed]在数据库中使用默认值是不好的做法吗? [关闭]
【发布时间】:2009-11-09 15:20:11
【问题描述】:

代码不应该处理默认值而不是数据库吗?

【问题讨论】:

  • 很多不同的意见。从答案中学到了很多,但仍然需要阅读其中的一些。在我们的产品中,只有一个应用程序访问数据库,并且在接下来的几个月中可能会保持这种状态。但这可能会改变,所以我会记住这一点。谢谢。

标签: database-design


【解决方案1】:

您可以在数据库中执行的任何操作通常都更加健壮。如果您处理默认值,如果仅在您的应用程序中未指定任何值,则将使用默认值,并且有人设法通过您的应用程序以外的其他方式连接到您的数据库(相信我 - 用户 WILL尝试使用 Excel 或其他工具进行连接)- 然后数据库是完全开放的,用户可能会插入糟糕的数据。

参照完整性和检查约束也是如此。我相信如果你尝试在数据库上设置尽可能多的这些约束,你会更好——那么无论用户如何连接,如果他没有向你发送任何东西,你都可以设置合理的默认值。

不要让应用程序处理您的检查 - 将其留给数据库!

此外,如果您不必指定所有“明显”的默认值,例如“LastChangedOn”日期列的“getdate()”等,它会使您的 SQL 插入语句更加精简和简洁。

【讨论】:

  • 我认为他的意思是在数据库中保留日期和此类 NULL 之类的内容,并在客户端代码中显示默认值。
  • jldupont- 使用数据库特定功能不会锁定你。我见过人们因为同样的(有缺陷的)推理而不使用主键!
  • jldupont:您多久切换一次数据库与多久更改一次可能会破坏验证过程的代码?
  • @jldupont:默认值几乎可以跨所有 SQL 数据库系统移植。如果您担心您的应用程序依赖于数据存储(在某些情况下这是一个合理的担忧),您可能应该考虑自己滚动。但是,如果您要使用 DBMS,请让 DBMS 完成它所设计的工作。
  • @Mark- 我认为很多人忘记的是在数据库中使用这些功能使数据库自我记录(我知道我可以将表 x 连接到表 y)。我知道我见过的所有 WTF 数据库都不使用参照完整性。
【解决方案2】:

这取决于您如何看待“默认”值。这样想:如果更改默认值会发生什么?如果要更新现有值,则默认值应仅在程序代码中,但如果应保留现有值,则应将默认值存储在数据库中。

【讨论】:

    【解决方案3】:

    代码默认值更容易进行单元测试。

    代码默认支持多种场景。 DB 列默认值是一刀切。例如,DB 列的默认值可能因客户类型而异。

    DB 列默认值对于维护开发人员通常是不透明的,因为它们远离 INSERT 语句,INSERT 语句通常位于中间层代码、存储过程等中。无论哪种方式,默认值的存在或不存在都可能令人惊讶。

    DB 列默认值保护数据库免受客户端懒得填写默认值,这是数据损坏的一种形式。

    客户端开发人员可以破坏这两种默认设置。在中间层使用有缺陷的默认设置为开发人员设置障碍更容易。 AFAIK,没有数据库允许您要求字段在 INSERT 上采用默认值。 (编辑:TRIGGER 可以强制执行此操作,但您必须将默认值复制到您的触发器,并且 TRIGGER 会用默认值覆盖任何插入的值)这可能很重要的一个示例是人们用于未知但未来的各种令牌日期,或未知但已过去的日期,或者他们是否使用包含时间的 GETDATE() 或者是否使用包含年、月、日且没有时间的默认日期可能很重要。

    我建议确保默认值存在于它们在数据库中有意义的位置,但实际上不要使用它们。数据库默认值应该是最后手段的默认值,并且默认值应该牢固地位于中间层(即存储过程,数据访问层)。 DB 列默认值就像一个异常处理程序——当有人不小心忘记提供一个值时,应该使用什么值来防止数据损坏?

    【讨论】:

      【解决方案4】:

      恰恰相反。数据库应始终提供默认值,以确保添加的记录有效且有意义。请记住,您在编写应用程序时无法预测最终将哪些代码添加到数据库中。

      这并不是说您可能没有应用程序指定的第二级默认数据,该数据取决于创建数据时的应用程序状态。

      因此,假设您的员工状态代码可以是“P”(待定)、“A”(在职)、“T”(已终止)或“R”(已退休)。例如,您应该在数据库级别指定人们是作为“P”还是“A”进入系统(或者可能是未分配的第五个代码)。但是您的应用程序可以并且应该要求创建员工记录的用户从(例如)一组单选按钮中选择一个选项,并在插入记录时使用该值。

      【讨论】:

        【解决方案5】:

        我通常认为代码应该注意默认值。这将有助于保持您的数据库精益求精。不过,如果您的数据库似乎有过多的空字段,您可能需要重新考虑设计。

        示例

        假设您有一个包含一百万行或更多行的表。在此表中,您有一个可能有 5% 的时间填充的日期时间列。随着时间的推移,您将通过存储 NULL 默认值节省的空间量将使必要的默认检查变得更值得。

        【讨论】:

        • 我不同意——这绝对应该由数据库处理。否则,如果有人设法通过您的应用以外的其他方式连接到您的数据,他们可能会输入无效或无用的数据。
        • @marc_s:但这是 IMO 普遍的“安全”问题。
        • @marc_s- 问题是人们是否会联系。我曾开发过肯定是这种情况的应用程序,以及数据库完全孤立于特定应用程序的其他应用程序。我想另一个问题是这是否会随着时间而改变。
        • 您为什么想要一个“精益且平均”的数据库而不是具有数据完整性的数据库?
        • 空日期时间而不是 1900/01/01 如何导致完整性降低?
        【解决方案6】:

        与大多数“代码与数据库”论点一样,这取决于。

        如果您的数据库(或表)将被许多不同的客户(即不紧密合作的团队)访问,那么数据库应该保护自己。理想情况下,一切都应该通过存储过程来完成。

        如果单个应用程序可以访问数据库,则该应用程序可以包含业务逻辑。在这种情况下,一切都应该由一个应用程序完成,并且该应用程序访问数据库。

        【讨论】:

        • +1。 @Wisty- 这是一个很好的观点。
        • 恕我直言,我总是警惕以“如果最简单的情况......”开头的设计。根据我的经验,您永远无法提前知道是否只有一个应用程序会访问数据库,事实上,无论一开始的计划是什么,未来都会添加各种实用程序以进行批量添加,这是一个很好的选择加载、维护、模式迁移等。由于即使在最简单的情况下,在代码中使用默认值也没有优势,为什么不同时面向未来并简化应用程序?
        【解决方案7】:

        如果您关心数据完整性(如果您不关心,为什么要有数据库?),您需要它们所属的数据库中的默认值。仅在代码中这样做是不负责任的。数据从应用程序代码以外的其他来源进入数据库。

        【讨论】:

        • 拥有一个默认值可以减少对数据的保护。它的默认值使 INSERT 更容易,而不是指定一个实际值。
        【解决方案8】:

        您可能需要考虑更改默认设置所需的条件。如果您的应用程序在内部,那么更改可能并不难,但如果它在您的客户站点上,那么对数据库进行更改可能是一个非常困难的过程。如果您有成百上千的客户,并且您需要说服他们的 DBA 授予您更新进程 SA 对数据库的访问权限,您将会后悔将任何应用程序逻辑放入数据库(包括默认值)。

        【讨论】:

          【解决方案9】:

          数据库旨在记录事实的断言。

          允许用户做出不完整的断言并让 dbms 对不完整的部分做出沉默的假设,这是非常糟糕的。

          如果您想要可以长时间使用的强大、可靠的系统,那么不要让该系统的任何部分对用户没有说的话做出假设。

          在演示级别处理默认值,其他任何地方都没有。并以这样一种方式处理它们,使用户无法看到他提交的数据(所有数据!)。

          【讨论】:

            【解决方案10】:

            除非该值与您的业务逻辑完全分离,否则我会说是的,这是不好的做法。至少根据分层模型,业务层与数据层是分开的。

            请记住:
            - 将默认值放在列上并不能保证数据完整性(应用程序应该能够处理放在列中的任何值)
            - 以某种方式在数据库中复制业务逻辑的麻烦和费用并不能保证数据的完整性。

            实现数据库安全的最明智的方法就是拥有数据库安全。例如,如果恶意用户设法破坏了该安全层,那么无论数据限制如何,您的数据都没有机会。

            【讨论】:

              猜你喜欢
              • 2013-06-23
              • 2010-09-26
              • 2018-06-28
              • 1970-01-01
              • 2016-08-18
              • 1970-01-01
              • 1970-01-01
              • 2011-12-12
              相关资源
              最近更新 更多