返回

MySQL 自动生成的列中 NULL 值难题:解决方案与常见问题

mysql

## MySQL 自动生成的列中的 NULL 值难题

### 问题背景

如果你在 MySQL 中定义了具有生成表达式或虚拟列的列,那么这些列的值将从其他列或表达式计算得出,而不是存储在表中。我们最近遇到一个问题,涉及到使用 GENERATED ALWAYS AS 子句创建的自动生成列。

### 问题

我们创建了一个名为 participants 的表,其中包含以下列:

  • project:一个 INT 列,使用以下生成表达式创建:
GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(data, '$.project'))) STORED NULL

当我们尝试向 project 列插入 NULL 值时,我们遇到了以下错误消息:

Error: Field 'project' doesn't have a default value

### 问题原因

即使 project 列被声明为允许 NULL 值,但生成表达式的限制却阻止了这种情况。生成表达式 JSON_UNQUOTE(JSON_EXTRACT(data, '$.project'))data 列中的 JSON 数据中提取 project 值。如果 data 列中的 JSON 数据中没有 project 键或键的值为 NULL,则生成表达式将返回 NULL

生成的列不能存储 NULL 值,因此当生成表达式返回 NULL 时,会引发错误。

### 解决方案

有两种方法可以解决这个问题:

#### 解决方案 1:使用 IFNULL()COALESCE() 函数

我们可以使用 IFNULL()COALESCE() 函数将 project 列的生成表达式包装起来。这些函数将返回第一个非 NULL 参数,即使其中一个参数是 NULL

修改后的生成表达式如下:

GENERATED ALWAYS AS (IFNULL(JSON_UNQUOTE(JSON_EXTRACT(data, '$.project')), 0)) STORED NULL

现在,如果 data 列中的 JSON 数据中没有 project 键或键的值为 NULLproject 列将返回 0 而不是 NULL

#### 解决方案 2:使用 JSON_VALUE() 函数

我们还可以使用 JSON_VALUE() 函数从 data 列中的 JSON 数据中提取 project 值。JSON_VALUE() 函数支持使用默认值,因此我们可以指定一个默认值,当 project 键不存在或为 NULL 时返回该值。

修改后的生成表达式如下:

GENERATED ALWAYS AS (JSON_VALUE(data, '$.project', 0)) STORED NULL

现在,如果 data 列中的 JSON 数据中没有 project 键或键的值为 NULLproject 列将返回 0 而不是 NULL

### 总结

MySQL 中的自动生成的列非常有用,但有时它们可能会带来挑战。通过了解这些列的限制和使用正确的函数或表达式,我们可以克服这些挑战,充分利用自动生成的列。

### 常见问题解答

1. 为什么生成的列不能存储 NULL 值?

生成的列是从其他列或表达式计算得出的,这些值不是实际存储在表中的。因此,它们无法存储 NULL 值。

2. 如何处理生成表达式返回 NULL 的情况?

我们可以使用 IFNULL()COALESCE()JSON_VALUE() 函数来处理这种情况。这些函数将返回第一个非 NULL 参数,即使其中一个参数是 NULL

3. 为什么使用 IFNULL()COALESCE() 函数需要指定一个默认值?

IFNULL()COALESCE() 函数需要一个默认值作为第二个参数,以便在第一个参数为 NULL 时返回该值。

4. 如何使用 JSON_VALUE() 函数指定默认值?

JSON_VALUE() 函数的第三个参数是默认值。如果 JSON_VALUE() 函数无法找到指定的键或该键的值为 NULL,它将返回指定的默认值。

5. 我还可以使用哪些函数来处理生成的列中的 NULL 值?

除了 IFNULL()COALESCE()JSON_VALUE() 函数外,还可以使用其他函数,如 NULLIF()ISNULL()