将字段留空更好还是用空填充?

Posted

技术标签:

【中文标题】将字段留空更好还是用空填充?【英文标题】:Is leaving a field empty better or filling it with null? 【发布时间】:2016-04-03 20:49:36 【问题描述】:

我有一个表,其中包含一个名为 first_name 的列。用户不强制填写,有时用户将其留空。现在我想知道:将null 值定义为默认值会更好吗?

【问题讨论】:

这取决于您的系统设计。 如果您的用户发送空数据,请将其插入为 NULL 或在您的插入语句中保留该列。例如:insert into tablename (id, last_name) values (123, 'Smith');insert into table (id, first_name, last_name) values (123, NULL, 'Smith'); 可能重复/回答***.com/questions/5618357/… 您的选择。选择一个并在整个应用程序中保持一致。我会亲自使用第二个,我明确使用 NULL 作为 first_name。 我确定这是重复的,但与链接的答案不同,它不应该依赖于愚蠢的数据库细节。相反,它应该对定义的数据进行建模。例如,从不询问名字和询问但没有得到回应名字之间有区别吗? 【参考方案1】:

定义default null 是多余的。如果您没有明确定义默认值,则如果未提供任何值,该列将默认为 null。一些人和项目标准喜欢明确声明这些 null 默认值,但它没有真正的目的,而且比其他任何事情都更重要。

【讨论】:

TIMESTAMP 列上试试。 @LightnessRacesinOrbit “TIMESTAMP”列到底是什么意思? Lightness 是说create table test2 (id int not null, ts timestamp default null); 会抛出错误ERROR 1067 (42000): Invalid default value for 'ts' @zedfoxus:不,我指出omitting the explicit default for TIMESTAMP columns is not the same as writing DEFAULT NULL,使后者远非“多余”(尽管这似乎从 mysql 5.6 开始发生了变化)。 啊哈,我为误解道歉。谢谢你帮助我理解。 @LightnessRacesinOrbit【参考方案2】:

问题是 Null 好还是不好?

根据我在您提到的场景中的经验,您必须放置默认的空值而不是 null。通过这种方式,您可以节省脚本来检查其是否为空,您可以只检查它是否为空,或者不检查是否为 null 有点棘手。

我的意见如何。

【讨论】:

检查 NULL 并不“棘手”,以一种或另一种方式对列施加约束相当容易。大问题归结为设计和数据如何建模 - 特别是 1) 无数据和未知数据之间的区别是什么? 2) 如何始终如一地对待此类访问? @user2864740 Hassan 提到必须处理空值有点相关,因为它不仅会影响代码,还会将CONCAT(first_name, ' ', last_name) 延长到CONCAT(IFNULL(first_name, ''), ' ', IFNULL(last_name, ''))。这不是一件难事,但可能需要一些警惕。 是的,我想强调完全相同的事情。 null 根据场景有其自身的重要性,但@Shafizadeh 强调空点很好。 另见COALESCE(...)【参考方案3】:

使用NULL 是完全有效的,如果它意味着一个字段没有给出或未知。这真的没有什么区别,这是一个品味问题,但有时知道什么时候没有给出比查询空字段或空白字段非常有用。

【讨论】:

【参考方案4】:

考虑下表:

create table test1 (
  id int not null,
  first_name varchar(50), -- nullable
  last_name varchar(50)   -- also nullable
);

如果您的 UI 中未提供 first_name,您可以选择不向该字段插入数据,方法是:

insert into test1 (id, last_name) values (123, 'Smith');

或者,您可以选择为 first_name 显式提供 NULL,如下所示:

insert into test1 (id, first_name, last_name) values (123, NULL, 'Smith');

-- you could also do like this below:
-- insert into test1 values (123, NULL, 'Smith');
-- I just like providing explicit fieldnames and values

无论您选择哪种方式,只要在整个应用程序中保持一致即可。你的结果看起来是一样的:

+-----+------------+-----------+
| id  | first_name | last_name |
+-----+------------+-----------+
| 123 | NULL       | Smith     |
| 123 | NULL       | Smith     |
+-----+------------+-----------+

所以 - 回答真正的问题:不要在创建表时定义显式 null。

提供 '' 或 NULL 时,请确保您保持一致。如果有些 first_name 是 '' 而有些是 NULL,那么您的 select 语句必须是:

select * from test1 where first_name is NULL or first_name is '';

这又带来了一点——如果用户输入“”(4 个空格)会怎样?您必须确保 first_name 符合某些标准,并且在输入数据库之前,first_name 的修剪版本要经过验证。如果您的数据库以 '', ' ', ' ' 等结尾,您将不得不不断运行:

select * from test1 where first_name is NULL or trim(first_name) = '';
--or--
--select * from test1 where first_name is NULL or length(trim(first_name)) = 0;

与 NULL first_name 的一致性将有助于自信地查询。

【讨论】:

【参考方案5】:

如果您希望列的默认值为NULL,则写为DEFAULT NULL

说更短的代码更好,我们可以依靠“默认默认值”为我们完成这项工作,这一切都很好,但事实上,这个问题的每个现有答案都会让您容易出现潜在的灾难性错误证明这是一种多么糟糕的方法!

看看这个:

CREATE TABLE `test` (`ts` TIMESTAMP);
SHOW CREATE TABLE `test`;

-- Result:
CREATE TABLE `test` (
  `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8

哇!那是什么DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP?那是what you get with a TIMESTAMP field with NOT NULL set and no explicit default。每当您更新该表中的一行时,时间戳列将重置为“现在”。这让很多人措手不及,这很好地说明了为什么做出假设是一种糟糕的做法。

所以,如果您要学习本手册,并且您绝对确信省略 DEFAULT NULL 会产生您想要的语义,那么请继续;但我认为,说出你的意思真的没有任何成本。

【讨论】:

哈哈:-) 谢谢。 +1

以上是关于将字段留空更好还是用空填充?的主要内容,如果未能解决你的问题,请参考以下文章

用空值填充文本框

如何合并数组中结构的不同模式(用空填充缺失的列)?

使用静态字段填充页面的剩余空间

Spring-Boot Config:如何在用于填充 Map<String, String> 的 yaml 键中保留空格

读取sqlite数据库时用SQLiteDataAdapter填充Datatable时遇到的问题。

填充事实表(数据仓库)和查询