SQL Null:区分未知值和无值值的首选方法

时间:2017-06-04 10:35:30

标签: sql null

假设我有一个简单的表,例如:

CREATE TABLE authors (
    id INT PRIMARY KEY,
    name VARCHAR(40),
    born DATE,
    died DATE
);

borndied日期都是可选的,因此它们可以包含NULL

可能是尚未出生的作者,不会将其列入表格,因此解释NULL的明显方法是日期未知。

但是,died日期存在一些歧义。 null可能意味着日期未知,或者作者尚未死亡。

允许未知日期和尚未发生的事件的首选方式是什么?

对于它的价值,我经常使用PostgreSQL,MySQL / MariaDB和SQL Server,所以这个问题不是特定于特定的DBMS。

3 个答案:

答案 0 :(得分:1)

处理此问题的一种方法是添加一个新列deceased,指示给定作者是否已过期。这使您的died日期字段免于对作者是否已经死亡负责。根据这种设计,如果作者尚未死亡(deceased是假的),那么我们就不会关心死亡日期。如果作者已经死亡,那么NULL值只会意味着日期真的未知。

答案 1 :(得分:1)

可能的解决方案是删除died列并添加下表:

CREATE TABLE deaths (
    id INT PRIMARY KEY REFERENCES authors(id),
    died DATE
);

在这种情况下,没有记录可能意味着作者没有死亡,而NULL died意味着作者已经死亡,但日期未知。

然后可以如下提取数据数据:

SELECT
    a.id, a.name, a.born,
    CASE WHEN d.id IS NULL THEN 'living' ELSE coalesce(d.died,'unknown') END
FROM authors a LEFT JOIN deaths d ON a.id=d.id;

d.id列用于确定是否存在匹配的行,否则作者被视为活着。如果存在匹配的行,则结果为died日期或合并的替代。

答案 2 :(得分:1)

这详细阐述了蒂姆的答案。我认为最好的方法是:

event

此代码验证以下条件:

  • 新的CREATE TABLE authors ( id INT PRIMARY KEY, name VARCHAR(40), isDead int not null, -- well, could be a bit or boolean or tinyint bornDate DATE, diedDate DATE, constraint chk_authors_isDead check (isDead in (0, 1)), -- valid values constraint chk_authors_isDead_diedDate check (isDead = 1 or diedDate is NULL), constraint check_authors_bornDate_diedDate check (bornDate <= diedDate) -- you might want to require that they are actually old enough to have written somthing ); 列仅采用0和1的值。
  • 如果isDead不是DiedDate,则NULL为1。
  • 提交人在他们去世前出生。

检查约束是标准SQL,并且受大多数数据库的支持 - 但不是MySQL的支持。