MySQL 自动生成的列中 NULL 值难题:解决方案与常见问题
2024-03-09 08:39:27
## 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
键或键的值为 NULL
,project
列将返回 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
键或键的值为 NULL
,project
列将返回 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()
。