【发布时间】:2023-03-10 10:11:02
【问题描述】:
我在一个网站上有一个表格,它有很多不同的领域。有些字段是可选的,而有些是强制性的。在我的数据库中,我有一个包含所有这些值的表,在用户没有放置任何数据的数据库列中插入 NULL 值或空字符串是更好的做法吗?
【问题讨论】:
我在一个网站上有一个表格,它有很多不同的领域。有些字段是可选的,而有些是强制性的。在我的数据库中,我有一个包含所有这些值的表,在用户没有放置任何数据的数据库列中插入 NULL 值或空字符串是更好的做法吗?
【问题讨论】:
使用NULL可以区分“不放数据”和“放空数据”。
更多区别:
NULL 的LENGTH 是NULL,空字符串的LENGTH 是0。
NULLs 排在空字符串之前。
COUNT(message) 将计算空字符串,但不计算 NULLs
您可以使用绑定变量搜索空字符串,但不能搜索NULL。这个查询:
SELECT *
FROM mytable
WHERE mytext = ?
无论您从客户端传递什么值,都不会匹配mytext 中的NULL。要匹配NULLs,您必须使用其他查询:
SELECT *
FROM mytable
WHERE mytext IS NULL
【讨论】:
我不知道这里的最佳实践是什么,但我通常会倾向于使用 null,除非您希望 null 表示与空字符串不同的东西,并且用户的输入与您的空字符串定义相匹配。
请注意,我是说您需要定义您希望它们如何不同。有时让它们不同是有意义的,有时则不然。如果没有,只需选择一个并坚持下去。就像我说的,大多数时候我倾向于使用 NULL。
哦,请记住,如果该列为空,则记录几乎不会出现在基于该列进行选择(在 SQL 术语中具有 where 子句)的任何查询中,除非选择是当然是空列。
【讨论】:
如果您曾经计划切换数据库,需要考虑的一件事是Oracle does not support empty strings。它们会自动转换为 NULL,您无法使用 WHERE somefield = '' 之类的子句查询它们。
【讨论】:
Steve B.:看到这个问题:stackoverflow.com/questions/1171196/…
要记住的一件事是,NULL 可能会使您的代码路径更加困难。例如,在 Python 中,大多数数据库适配器/ORM 将 NULL 映射到 None。
比如:
print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
可能会导致“你好,没有 Joe Doe!”为了避免它,你需要这样的代码:
if databaserow.title:
print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
else:
print "Hello, %(firstname) %(lastname)!" % databaserow
这会使事情变得更加复杂。
【讨论】:
最好插入 NULL 以在 MySQL 中的数据库中保持一致性。外键可以存储为NULL,但不能存储为空字符串。
您将遇到约束中的 空字符串 的问题。 您可能必须插入带有 唯一空字符串 的假记录以满足外键约束。我猜这是不好的做法。
【讨论】:
如果您在唯一索引中使用多个列,并且这些列中至少有一个是强制性的(即,必填表单字段),如果您将索引中的其他列设置为 NULL,您最终可能会出现重复的行。这是因为 NULL 值在唯一列中被忽略。在这种情况下,在唯一索引的其他列中使用空字符串以避免重复行。
唯一索引中的列: (event_type_id、event_title、日期、位置、网址) 示例 1: (1, '烧烤', '2018-07-27', null, null) (1, 'BBQ', '2018-07-27', null, null) // 允许和重复。 示例 2: (1, '烧烤', '2018-07-27', '', '') (1, 'BBQ', '2018-07-27', '', '') // 不允许,因为它是重复的。这里有一些代码:
CREATE TABLE `test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`event_id` int(11) DEFAULT NULL,
`event_title` varchar(50) DEFAULT NULL,
`date` date DEFAULT NULL,
`location` varchar(50) DEFAULT NULL,
`url` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `event_id` (`event_id`,`event_title`,`date`,`location`,`url`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
现在插入这个看看它是否允许重复的行:
INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`,
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);
INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`,
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);
现在插入它并检查它是否不允许:
INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`,
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');
INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`,
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');
所以,这里没有对错。由您决定什么最适合您的业务规则。
【讨论】: