SQL 服务器:为什么可以在 NON-NULLable 列上设置默认 NULL 值?

SQL Server: why is it possible to set default NULL value on NON-NULLable column?

今天我正在研究两个环境之间模式差异的问题,我意识到这与在非 Nullable 列上设置为 NULL 的默认值有关。

令我惊讶的是,我决定对其进行测试,如您所见,SQL 服务器允许您在不允许的列上设置 NULL。

CREATE TABLE TestTable (
    [Id] [uniqueidentifier] NOT NULL,
    [BooleanColumn] BIT NOT NULL DEFAULT NULL 
)   

我希望看到某种语法错误。

为什么这可能?听起来很奇怪。

为了强化 Larnu 的评论:通过设置默认值 null(或简单地接受系统默认值),您明确表示未能插入域值将导致错误。假设您将默认值设置为 1。那么我可以插入一行而不将该列指定为插入列表的一部分,或者为该列提供任何值。这可能会导致不希望或无法预测的行为。具有 null 默认值的 not null 表示“如果要创建此集合的成员,则必须先定义此属性”

Fiddle example from Aaron Bertrand

在评论中,您还与 C# bool 进行了比较,但 C# bool 字面上不能 null,这与 SQL bit,可以。为了进行比较,您必须与 C# bool? 进行比较,其默认值 null.


C c = new();
if (c.b is null) Console.WriteLine("it is null"); // prints "it is null"

internal class C
{
   public bool? b;
}

编辑:从评论来看,这个论点似乎有点抽象,所以我将尝试使用不同的示例和不同的数据类型使其更清楚。

假设我在我的域中有一个“客户”的想法。 Customer 有一个 name 属性。在我的模型中(根据我的业务需求),如果没有 name.

就能够创建 Customer 没有任何意义

在这种情况下,我指定 name 列因此是 not null

但是我应该指定什么作为默认值?显然,为 name 指定默认值并没有任何意义。如果我们将默认设置为“Bob”,我们真的只是在自欺欺人。如果我们将默认值设置为空字符串,我们现在搬起石头砸自己的脚,因为我们所做的一切都是规避业务规则,如果这些客户没有 Customers,我们实际上还没有创建任何有意义的 Customers =20=].

所以在我的模型中,我想指定要创建 Customer,您必须为 name 提供合法值。因此,我创建了 not null 列并故意选择不提供可接受的默认值。

当然,当您出现插入数据时,您仍然可以使用空字符串显式填充 name 列...但是现在,这取决于您,作为创建数据的人。该模型已经指定了它所期望的,你必须非常谨慎地规避它。如果我们给该列一个无意义的默认值,人们可能会“无意中”违反业务规则,甚至没有意识到这一点。