19

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

4

10 回答 10

16

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

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

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

于 2010-02-17T21:49:21.730 回答
7

我个人发现可以很好地使用默认值的一个实际案例是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
于 2010-02-17T21:50:08.800 回答
4

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

于 2010-02-17T21:50:27.693 回答
4

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

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

于 2010-02-17T21:57:55.693 回答
4

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

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

免责声明:我生活在一个面向对象的世界并使用 Linq2Sql。

于 2011-06-20T09:37:33.297 回答
3

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

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

然后有一些列通常在数据输入上被赋予一个值,这些值可能会在以后发生变化。状态栏之类的东西。

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

于 2010-02-17T22:57:35.587 回答
2

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

于 2010-02-17T21:57:47.453 回答
1

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

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 转换处理。这可能并不适用于所有场景,特别是当相关表包含数百万行并且存储空间是一个问题时。

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

于 2010-02-17T23:56:28.160 回答
1

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

于 2021-06-03T15:38:16.087 回答
0

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

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

为了实用,我们可以像往常一样做一个例外,并允许默认逻辑进入数据库。

于 2010-02-17T22:05:17.983 回答