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
列...但是现在,这取决于您,作为创建数据的人。该模型已经指定了它所期望的,你必须非常谨慎地规避它。如果我们给该列一个无意义的默认值,人们可能会“无意中”违反业务规则,甚至没有意识到这一点。
今天我正在研究两个环境之间模式差异的问题,我意识到这与在非 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
列...但是现在,这取决于您,作为创建数据的人。该模型已经指定了它所期望的,你必须非常谨慎地规避它。如果我们给该列一个无意义的默认值,人们可能会“无意中”违反业务规则,甚至没有意识到这一点。