【问题标题】:Should a database table have default values?数据库表应该有默认值吗?
【发布时间】:2011-01-18 01:59:35
【问题描述】:

我正在与工作中的开发人员讨论表应该使用默认值的问题。对此是否有硬性规定,还是最佳实践中的灰色地带?

【问题讨论】:

    标签: sql database column-defaults


    【解决方案1】:

    我的规则:如果许多记录将使用该默认值(至少在最初),那么我喜欢将其用作默认值。例如,在线商店中产品的图像表可能具有images/NoPictureYet.png 的默认路径。最终,这些将被替换,但是对于图片根本不存在的批量加载数据(也许其中大多数永远不会存在!),默认值是有意义的(至少对我来说)。

    如果没有合理的默认值(例如客户数据库中的“名字” - 我不希望我的名字默认为“名字”),那么我将其设为不可空且无默认值 - 这是应用程序的责任以确保输入正确的值。

    但对此没有硬性规定。这一切都有点不同;)

    【讨论】:

      【解决方案2】:

      我个人发现可以很好地使用默认值的一个实际案例是last_modified 列。

      此列永远不会被存储过程或业务逻辑更新,而是在行中的任何值发生更改时由触发器自动更新。但是,它也默认设置为GETDATE(),这样新行的值将包含创建时间的时间戳,基本上是上次修改的时间。

      ALTER TABLE users ADD CONSTRAINT dc_users_last_modified
                        DEFAULT GETDATE()
                        FOR last_modified;
      

      更新触发器将如下所示:

      CREATE TRIGGER trigUpdate_users 
      ON users 
      FOR UPDATE 
      AS 
      BEGIN 
          IF NOT UPDATE(last_modified) 
              UPDATE users SET last_modified = GETDATE() 
              WHERE user_id IN (SELECT user_id FROM inserted);
      END 
      GO
      

      【讨论】:

      • 不是真正意义上的“默认”。
      • 我更喜欢 created_datemodified_date 列的触发器。
      • @Daniel Vassallo:modified_date 必须作为更新触发器完成,我喜欢 created_date 的代码与 modified_date 保持一致。 ;) 也许不是最好的理由,但是......哦,好吧!
      【解决方案3】:

      不能应用任何硬性规定。这取决于列。例如,使用默认订单类型可能是完全明智的,但默认客户电话号码的想法没有意义。

      【讨论】:

        【解决方案4】:

        我会说它是一个灰色区域。通常,我不会设计具有大量默认值的新数据库,但在增强现有系统时经常需要使用它们。

        例如向现有数据库添加一个新的非空列。您可能不想(或无法)更新插入该表的所有代码,因此您需要为其设置默认值以确保任何“旧”代码仍然可以插入数据(假设默认值是合适的当然对于遗留代码)。

        【讨论】:

          【解决方案5】:

          tl;dr: 默认值是业务逻辑,我想要对象模型中的业务逻辑。因此,数据库不能包含默认值。

          例如在数据库中,我有一个位字段:IsANicePerson。此字段转换为 Person 类的属性。天性乐观,我希望此属性的默认值为“真”。所以在 Person 类中我实现了这个(作为 isANicePerson 支持字段的默认值)。如果我允许数据库中的默认值,我将不得不复制这个逻辑。重复的代码/逻辑是不好的。因此我反对默认值。

          免责声明:我生活在 OO 世界并使用 Linq2Sql。

          【讨论】:

            【解决方案6】:

            如果列必须有值(不为空),则默认值很重要。事实上,如果您将列从允许空值更改为不允许它们,则非常有必要使用默认值,因为并非所有现有代码都可以填充一个值。有时在这种情况下,默认值类似于“未知”。如果您想使用 WITH VALUES 为将列更改为 NOT NULL 的 ALTER TABLE 语句中字段为空的现有记录提供默认值,则尤其如此

            默认值对于用户界面通常不处理的字段至关重要。例如,我们在 date_inserted 和 user_inserted 列上有默认值,用户甚至都不知道它们的存在。如果许多不同的应用程序可以填充数据以确保没有人忘记这些列,这一点尤其重要。

            然后,有些列通常在数据输入中被赋予一个值,以后可能会更改。状态栏之类的东西。

            尽管如此,许多列实际上并没有默认值。用户的默认地址或名称是什么?

            【讨论】:

            • 您做出的一个区别似乎取决于数据是真正的“信息”还是仅仅是家务?用户的电话号码是有关相关实体(该特定用户)的一段数据。添加或更改记录的时间不是。从某种意义上说,这些东西根本不是“信息”,更像是审计线索。一种解决方案是将所有内务管理信息(内部和外部主键、添加和更改的时间以及由谁、记录是否标记为已删除等)存储在与实际数据不同的单独表中。然后您可以删除数据并分发该更改。
            【解决方案7】:

            应该很简单。如果数据通常对于每一行都是唯一的,例如客户电话号码,或者默认值很可能会随着时间而改变,那么我不会使用它。这意味着它实际上只对填充 CreateDate、ModifiedDate 或其他此类性质的列有用。

            【讨论】:

              【解决方案8】:

              以下是我个人使用的关于默认值的准则,这些准则过去对我很有帮助。在以下示例中,考虑具有多个应用程序的数据库后端,这些应用程序对后端具有读/写访问权限。在这些情况下,数据库必须定义数据的建模方式,从而确保数据的完整性。

              1) CreatedDate 和 ModifiedDate 列。这些列通常会将 getdate() (sql server) 定义为默认值。正如其他帖子中提到的,这些字段随后可以使用触发器等进行更新。

              2) 布尔状态列。示例:“IsDefault”、“IsDeleted”(用于审计)、“IsActive”等。所有这些字段通常都有一个逻辑默认状态,应该由数据模型定义。例外情况显然是可空的三态布尔字段,其中空状态表示有关存储在记录中的数据的某些内容。

              3) 数据约束定义:AllowNull=false 且未定义默认值的列。换句话说,应用程序需要一个值。

              4) 查找表外键标识:这可能不是标准,但对于很多查找表外键,我将定义一个默认值,涵盖记录的初始状态。因此,例如,在“事件”表中,外键列“EventTypeId”(int-autoincrement)将具有默认值 1 并表示“常规”或其他内容。这将涵盖大多数情况,例如,我想记录一个事件但不关心特定类型 ID。

              5) 非关键字符串列:“Description”、“Comment”等。对于这些列,我通常将 '' 定义为默认值,纯粹是为了简化 System.DbNull=>应用程序中的 Null 转换处理。这可能并不适用于所有场景,尤其是当相关表包含数百万行且存储空间存在问题时。

              所以总而言之,使用默认值来确保存储在数据库中的实际数据的数据完整性。数据模型应该在自身内部定义这些数据完整性规则,并且任何与之交互的应用程序都将并且应该强制遵守这些规则。另请注意,这不是教义,总会有例外。分别考虑每个场景,以便它对您的数据库/应用程序有意义。

              【讨论】:

                【解决方案9】:

                默认值可用于审计目的。如果应用程序不包含该字段的值,则默认值很有用,例如上次更新的日期时间戳。作为规则,应用程序应负责提供必填字段。如果未提供必填字段,数据库将抛出错误。你不想要魔法编码,因为那会让人困惑

                【讨论】:

                  【解决方案10】:

                  绝对是一个灰色地带。经典的问题是在数据库中放入多少业务逻辑。

                  如果我们想成为纯粹主义者并说数据库中不属于任何业务逻辑,那么答案就是永远不要使用它们。

                  根据实际情况,我们可以像往常一样创建一个例外,并允许将默认逻辑放入数据库中。

                  【讨论】:

                  • 多么愚蠢,必须在数据库级别强制执行数据完整性,否则您就没有数据完整性。在应用程序中强制执行默认值或约束或触发逻辑充其量是短视的。这几乎可以保证数据不正确,因为数据库通常会在应用程序之外受到影响。
                  • 同意约束。但不是默认值,它不是数据完整性。
                  猜你喜欢
                  • 2018-09-01
                  • 2018-05-21
                  • 2013-02-02
                  • 2011-08-06
                  • 2019-04-02
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-03-26
                  相关资源
                  最近更新 更多