代码之家  ›  专栏  ›  技术社区  ›  Blorgbeard

对于非空列,我应该有多自由?

  •  23
  • Blorgbeard  · 技术社区  · 17 年前

    我正在设计一个数据库模式,我想知道我应该使用什么标准来决定是否应该使用每个列 nullable 或者不是。

    必须 填写一行对我的申请有任何意义吗?

    或者我应该标记所有我希望永远不为空的列吗?

    小数量与大数量的非空列对性能的影响是什么?

    我假设很多非空列会使插入速度减慢一点,但实际上可能会加快选择速度,因为查询执行计划生成器有关于这些列的更多信息。。

    一个比我更有知识的人能告诉我真相吗?

    15 回复  |  直到 15 年前
        1
  •  30
  •   kquinn    17 年前

    老实说,我一直认为NOTNULL应该是默认值。NULL是一个奇怪的特例,无论何时使用它,都应该为它设置一个特例。另外,将列从NOTNULL更改为nullable要比将列从NOTNULL更改为nullable容易得多。

        2
  •  15
  •   dkretz    15 年前

    “我是否应该仅将行中绝对必须填写的列标记为NOTNULL,以便对我的应用程序有任何意义?”


    编辑:

    我认为可空字段的另一个论点最终是最有说服力的,那就是用例论点。我们都受到数据输入表单的约束,这些表单要求某些字段具有值;我们都放弃了表单,在那里我们对必填字段没有合理的值。最终,应用程序、表单和数据库设计只有在反映用户需求的情况下才是合理的;很明显,有很多很多数据库列,用户不能为它们提供任何价值——有时在业务流程中的给定点,有时甚至永远。

        3
  •  12
  •   Mark Brackett    17 年前

    允许随机事物为空是迟早的事, 一场噩梦。谨慎地使用NULL,并知道它在您的逻辑中的含义。

    编辑:似乎有一个想法,我在争论 有用,但只在预期的地方。

    WHERE DateOfDeath IS NULL .

    但是,空OrderDate意味着什么?订单还没有下?即使订单表中有记录?空地址怎么样?在让NULL成为一个值之前,这些想法应该经过你的头脑。

    返回DateOfDeath-人员查询 WHERE DateOfDeath > '1/1/1999' 必须在1999年后死亡 . 这就是你想要的吗?如果没有,那么你最好包括 OR DateOfDeath IS NULL 要为空,您必须考虑这一点 每次编写查询时 . IME,对于10%左右的列来说,这是太多的精神税了,当它们为空时,实际上有合法的意义。

        4
  •  10
  •   singpolyma    17 年前

    我发现将列标记为NOTNULL通常是一个好主意,除非您对列中的NULL有有用的含义。否则,当您意识到自己不想要它时,您可能会意外地在其中找到NULL,并且更改会更加困难。

        5
  •  10
  •   user53794    17 年前

    我尽量避免在数据库中使用NULL。这意味着字符字段始终不为空。数字字段也一样,尤其是表示货币或类似物(股票、单位等)的任何内容。

    1. 可能不知道日期的日期(如离婚)

    我有时也会使用显式位字段表示“未知”/“未设置”(例如JobDescriptionCode和IsEmployeed)。

    我有几个核心原因:

    1. 在业务逻辑层中防止空值是一种乏味的工作浪费。。。只要不让它们进入数据库,就可以节省100行代码。

    我的首选默认设置:

    • 字符串->“”,也称为空字符串
    • 数字->0
    • 日期->今天或空(见例外#1)
        6
  •  7
  •   Steven Huwig    17 年前

    你可以找到Chris Date的 Database In Depth 这类问题的有用资源。你可以在这本书中领略他的想法 interview

    所以,是的,我确实认为SQL非常糟糕。

    • 重复行
    • 空值
    • 从左到右列排序
    • 未命名的列和重复的列名
    • 高冗余

    根据我自己的经验,几乎所有“计划的空值”都可以用一个子表更好地表示,该子表具有一个基表的外键。参与子表是可选的,这就是实际进行null/notnull区分的地方。

    这很好地映射到关系作为一阶逻辑命题的解释。这也是常识。当一个人不知道鲍勃的地址时,他会在自己的Rolodex中写下:

    Bob. ____
    

    或者,在没有鲍勃的实际地址之前,人们只是不为他填写地址卡吗?

    Why Nulls are Prohibited ."

        7
  •  4
  •   twblamer    17 年前

    关于NULL,我最喜欢的是:

    SELECT F1 FROM T WHERE F2 <> 'OK'
    

    …其中(至少在DB2中)不包括f2为null的任何行——因为在关系行话中,(null<'OK')为null。但您的目的是返回所有非OK行。您需要一个额外的OR谓词,或者将F2写入与“OK”不同的地方(这首先是特殊情况编码)。

    在我看来,NULL只是程序员的工具之一,就像指针算术或运算符重载一样,它需要与科学一样多的艺术。

    Joe Celko在SQL For Smarties中写到了这一点——在应用程序中使用NULL的陷阱在于它的含义没有定义。它可能意味着未知的、未初始化的、不完整的、不适用的——或者像上面这个愚蠢的例子一样,它是表示OK还是NotOK?

        8
  •  4
  •   Community Mohan Dere    9 年前

    谢谢你们的回答,伙计们。你给了我很多思考,并帮助我形成了自己的观点/策略,归结起来如下:

    当且仅当 该专栏将有一个特定的主题 对你的申请有意义。

    null有两个常见含义:

    • 直接来自用户的任何内容
      • 对于这些列,最好允许空值,否则只会 还是输入吧。
    • “0或1”关系的外键

    一般来说,如果您不能在列中为null想出一个有用的含义,那么它应该是 NOT NULL . 以后您可以随时将其更改为nullable。

    create table SalesOrderLine (
        Id int identity primary key,
        -- a line must have exactly one header:
        IdHeader int not null foreign key references SalesOrderHeader, 
        LineNumber int not null, -- a line must have a line number
        IdItem int not null, -- cannot have null item
        Quantity decimal not null, -- maybe could sell 0, but not null
        UnitPrice decimal not null, -- price can be 0, but not null
        -- a null delivery address means not for delivery:
        IdDeliveryAddress int foreign key references Address, 
        Comment varchar(100), -- null means user skipped it
        Cancelled bit not null default (0) -- true boolean, not three-state!
        Delivered datetime, -- null means not yet delivered
        Logged datetime not null default (GetDate()) -- must be filled out
    )
    
        9
  •  2
  •   danieltalsky    17 年前

    我倾向于同意多菲的观点。

    在应用程序中,当接收数据库空值并将其视为空值时,要认真考虑是否灵活,并且为自己提供了很大的灵活性,允许为未指定的值插入NULL。

    可能有很多情况下,您需要一些非常严重的数据完整性(和/或强烈的速度优化,不允许使用空字段),但我认为这些问题与确保每个字段都有默认值和/或设置为合理值所需的额外努力相比得到了缓解。

        10
  •  2
  •   Jonathan Leffler    17 年前

    坚持使用NOT NULL,直到有人痛苦地尖叫。然后尽可能不情愿地将其从一根柱子上移除。尽可能长时间地避免数据库中的空值。

        11
  •  2
  •   HLGEM    17 年前

    就我个人而言,我认为您应该根据列包含的数据类型、数据是否始终存在的真实要求以及输入时数据是否始终已知,将列标记为Null或notnull。当用户没有数据时,将列标记为NOTNULL将迫使用户补齐数据,这将使您的所有数据变得无用(这就是为什么您最终会得到垃圾数据,例如包含“0”的电子邮件字段thisissilly@Ihatethisaplication.com"). 不要求流程必须具备的某些东西(比如显示客户下订单内容的关键字段)也同样愚蠢。Null vice not Null是数据完整性的核心问题,请尽最大努力保持数据的可用性。

        12
  •  1
  •   Some Canuck    17 年前

    如果您可以长期考虑,那么列中的null会影响您如何设计查询。无论您使用CASE语句、COALESCE还是必须显式测试NULL值,都可以为您做出决定。

    从性能的角度来看,不用担心空值会更快。从设计的角度来看,使用NULL是一种简单的方法,可以知道某个项目从未填写过。有用的示例包括“UpdateDateTime”列。NULL表示项目从未更新过。

    就我个人而言,我允许在大多数情况下使用空值。

        13
  •  1
  •   Portman    17 年前

    这可能是显而易见的,但是 ,当列可为空时,每条记录将需要额外的1位存储。那么 一点 列可为null时将消耗100%以上的存储空间,而 唯一标识符

    在这种情况下,如果您的数据库有一个由单个位列组成的表,那么将该列设置为空的决定将使数据库的性能降低一半。但是,在绝大多数真实场景下,可空性不会对性能产生可测量的影响。

        14
  •  0
  •   Andrew Harry    17 年前

    使用“notnull”或“Null”应该主要由您的特定持久性需求驱动。

    值可为空表示有两个或三个状态(三个带位字段的状态)

    例如;如果我有一个名为“IsApproved”的位字段,并且该值是在比插入更晚的阶段设置的。然后有三种状态:

    1. “IsApproved”未被批准

    因此,如果一个字段可以被合法地视为未回答,并且没有合适的默认值。这些字段应被视为可为空

        15
  •  -1
  •   paulmurray    17 年前

    但是,这不是答案。

    可能是这样的:数据库中有两种类型的列—保存 结构 所容纳之物 数据的完整性。键是结构,用户可输入的字段是数据。其他事情-嗯-这是一个判断的决定。

    连接子句中使用的结构的内容通常不为null。作为数据的东西通常是可以为空的。