数据库表是否应具有默认值?

时间:2010-02-17 21:45:22

标签: sql database column-defaults

我正在与一位开发人员讨论如果表使用默认值的问题。对此有一个严格的规则,还是最佳实践中的灰色区域?

10 个答案:

答案 0 :(得分:14)

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

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

但对此没有严格的规定。这一切都有所不同;)

答案 1 :(得分: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

答案 2 :(得分:4)

不能应用严格的规则。这取决于列。例如,拥有默认订单类型可能是完全合理的,但客户电话号码默认的想法没有意义。

答案 3 :(得分:3)

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

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

答案 4 :(得分:3)

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

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

然后有些列通常会在数据输入上给出一个值,以后可能会更改。像状态列这样的东西。

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

答案 5 :(得分:3)

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

E.g。在数据库中我有一个字段:IsANicePerson。此字段转换为Person类的属性。由于天生乐观,我希望此属性的默认值为“true”。所以在Person类中我实现了它(作为isANicePerson支持字段的默认值)。如果我允许数据库中的默认值,我将不得不复制此逻辑。重复的代码/逻辑很糟糕。因此我反对默认值。

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

答案 6 :(得分:2)

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

答案 7 :(得分:1)

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

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

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

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

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

5)非关键字符串列:“描述”,“注释”等。对于这些列,我通常将''默认定义为简化System.DbNull =>应用程序中的空转换处理。这可能并不适用于所有情况,特别是当相关表包含数百万行并且存储空间存在问题时。

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

答案 8 :(得分:0)

绝对是一片灰色地带。经典的数据库问题是多少业务逻辑。

如果我们想要纯粹主义并且说数据库中没有业务逻辑,那么答案将永远不会使用它们。

实际上,我们可以像往常一样做出异常,并允许默认逻辑进入数据库。

答案 9 :(得分:0)

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