我正在设计一个数据库模式,我想知道我应该使用什么标准来决定每列是否应该nullable
.
我应该将那些绝对必须填写的列标记为NOT NULL ,以便对我的应用程序有任何意义吗?
或者我应该标记我打算永远不会为null的所有列?
小型与大量NOT NULL列的性能影响是什么?
我假设很多NOT NULL列会减慢插入速度,但它实际上可能加快选择速度,因为查询执行计划生成器有更多关于列的信息.
知道比我更多的人可以给我低调吗?
老实说,我一直认为NOT NULL应该是默认值.NULL是奇怪的特殊情况,每当你使用它时你应该为它做一个案例.另外,将列从NOT NULL更改为nullable要比从另一个方向更改更容易.
没有重大的性能后果.甚至不要考虑将此视为一个问题.这样做是一个巨大的早期优化反模式.
"我是否只应将那些绝对必须填写的列标记为NOT NULL,以便对我的应用程序有任何意义?"
是.就这么简单.使用NULLable列而不使用任何NULL值比使用NULL并且必须伪造它要好得多.无论如何,任何含糊不清的案例都会在您的业务规则中得到更好的过滤.
对于可空字段还有另一个论点,我认为最终是最引人注目的,即Use Case参数.我们都受制于需要某些领域价值的数据输入表格; 我们都放弃了我们对必填字段没有明智价值的形式.最终,应用程序,表单和数据库设计只有在反映用户需求时才是可辩护的; 并且很明显,有许多数据库列,用户无法提供任何价值 - 有时在业务流程的特定点,有时甚至是.
Err在NOT NULL一边.在某些时候,您将必须决定应用程序中"NULL"的含义 - 很可能,对于不同的列,它将是不同的东西.一些常见的情况是"未指定","未知","不适用","尚未发生"等等.您将知道何时需要其中一个值,然后您可以适当地允许NULLable列和编码它周围的逻辑.
允许随意的事情是NULL是,早晚,总是一个噩梦IME.小心谨慎地使用NULL - 并且知道它在逻辑中意味着什么.
编辑:似乎有一个想法,我正在争论NO null列.这是荒谬的.NULL 是有用的,但只有当它的预期.
Le Dorfier的DateOfDeath示例就是一个很好的例子.NULL DateOfDeath将指示"尚未发生".现在,我可以写一个视图LivingPersons WHERE DateOfDeath IS NULL
.
但是,NULL OrderDate意味着什么?订单还没有下订单?即使Order表中有记录?NULL地址怎么样?在让NULL成为值之前,应该通过这些想法.
返回DateOfDeath - 人们的查询WHERE DateOfDeath > '1/1/1999'
不会返回NULL记录 - 即使我们逻辑上知道他们必须在1999年之后死亡.那是你要的吗?如果没有,那么您最好包含OR DateOfDeath IS NULL
在该查询中.如果允许所有列都为NULL,则每次编写查询时都必须考虑这一点.IME,对于10%左右的列,当它们为NULL时实际上具有合法含义时,这是太多的精神税.
我发现将列标记为NOT NULL通常是个好主意,除非你对列中的NULL有一个有用的含义.否则,当您意识到自己不想要它时,您可能会意外地在那里找到NULL,并且更改会更难.
我尽量避免在数据库中使用NULL.这意味着字符字段始终不为空.对于数字字段也是如此,尤其是代表金钱或类似的东西(股票,单位等).
我有2个例外:
可能不知道日期的日期(例如,DivorcedOn)
可选的foriegn密钥关系(MarriedToPersonId).虽然有时候我在外键表中使用了"空白"行并且必须强制关联(例如JobDescriptionCode)
我还偶尔使用显式位字段来表示"未知"/"未设置"(例如,JobDescriptionCode和IsEmployeed).
我有几个核心原因:
NULL将始终导致数字字段中的问题.总是.总是.总是.无论你在某个点上多么小心选择X + Y,因为Total将会发生并且它将返回NULL.
NULL很容易在字符串字段中引起问题,通常是地址字段(例如,从地址中选择AddrLine1 + AddrLine2).
防止业务逻辑层中的NULL是一种繁琐的浪费...只是不要让它们在数据库中,你可以保存100行的代码.
我的首选默认值:
字符串 - >"",又名空字符串
数字 - > 0
日期 - >今天或NULL(见例外#1)
比特 - >假
您可能会发现Chris Date的深度数据库是这类问题的有用资源.你可以在这次采访中体验他的想法,他说:
所以是的,我认为SQL非常糟糕.但你明确地问它的主要缺陷是什么.嗯,这里有几个:
重复的行
空值
从左到右的列排序
未命名的列和重复的列名称
未能正确支持"="
指针
高冗余
根据我自己的经验,使用具有基表外键的子表可以更好地表示几乎所有"计划空值".参与子表是可选的,这是实际进行null/not null区分的地方.
这很好地解释了作为一阶逻辑命题的关系的解释.这也只是常识.当一个人不知道鲍勃的地址时,是否会写一个人的Rolodex:
Bob. ____
或者,只有一个人有一个实际的地址,他们是否只是为Bob填写地址卡?
编辑:日期的参数显示在数据库深度的第53-55页上,标题为" 为什么禁止空值 "部分.