喜迎
春节

MySQL 生成列


MySQL 生成列(Generated Column),也称为虚拟列,是一种特殊类型的列,其值由其他列的值通过表达式计算得出,而不是直接存储在表中。

基本概念

生成列分为两种类型:

  1. 虚拟列(VIRTUAL):值在查询时动态计算,不占用存储空间
  2. 存储列(STORED):值在插入或更新时计算并存储,占用存储空间

特点

  1. 表达式支持:可以使用大多数MySQL表达式,包括算术运算、函数调用、CASE表达式等
  2. 约束:虚拟列可以有NOT NULL约束,但不能有DEFAULT或AUTO_INCREMENT约束
  3. 索引:存储列可以建立索引,虚拟列也可以(MySQL 5.7.6+)
  4. 外键:不能作为外键引用

使用场景

  1. 简化查询:避免在查询中重复计算
  2. 数据一致性:确保派生值始终与源数据一致
  3. 性能优化:对存储列建立索引可以提高查询性能

创建生成列

1
2
3
4
5
6
7
8
CREATE TABLE employees (
id INT PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
full_name VARCHAR(100) GENERATED ALWAYS AS (CONCAT(first_name, ' ', last_name)) VIRTUAL,
salary DECIMAL(10,2),
annual_salary DECIMAL(10,2) GENERATED ALWAYS AS (salary * 12) STORED
);

修改生成列

1
2
ALTER TABLE employees 
MODIFY COLUMN full_name VARCHAR(100) GENERATED ALWAYS AS (CONCAT(first_name, ' ', last_name, ' (Employee)')) VIRTUAL;

删除生成列

1
ALTER TABLE employees DROP COLUMN full_name;

注意事项

• 虚拟列不能引用其他虚拟列

• 在MySQL 5.7中,只有存储列可以有索引

• 在MySQL 8.0中,虚拟列也可以有索引

• 虚拟列的值在查询时计算,可能影响性能(特别是复杂表达式)

PHP laravel中如何查找指定表中的生成列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 获取指定表的生成列
* @param string $tableName
* @return array
*/
public static function getGeneratedColumns(string $tableName): array
{
$database = env("DB_DATABASE");
$cacheKey = "db_generated_columns_{$database}_{$tableName}";
return RedisService::cacheObject($cacheKey, [], function () use ($tableName, $database) {
try {
return DB::table('information_schema.COLUMNS')
->where('TABLE_SCHEMA', $database)
->where('TABLE_NAME', $tableName)
->whereIn('EXTRA', [
'VIRTUAL GENERATED',
'STORED GENERATED',
'auto_increment', // 自增列
'DEFAULT_GENERATED',
'DEFAULT_GENERATED on update CURRENT_TIMESTAMP', // 时间戳列
'on update CURRENT_TIMESTAMP' // 时间戳列
])
->select('COLUMN_NAME')
->pluck('COLUMN_NAME')
->toArray();
} catch (\Throwable $e) {
Log::error("Failed to get generated columns for table {$tableName} in database {$database}: " . $e->getMessage());
return [];
}
});
}

说明

虚拟列的内容不能修改,如果直接修改会报错,提示The value specified for generated column 'sc_gmv' in table 'sc_storage_game' is not allowed.

总结

MySQL 生成列为数据库设计提供了强大的功能,可以简化应用逻辑、提高数据一致性并优化查询性能。在 Laravel 中,通过封装服务类并结合缓存机制,可以高效地管理和使用生成列。开发者应根据具体业务场景选择虚拟列或存储列,并注意相关限制和最佳实践。

通过合理使用生成列,可以显著提升数据库设计的灵活性和性能,同时保持代码的简洁性和可维护性。


文章作者: Crazy Boy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Crazy Boy !
评 论
 上一篇
萝卜快跑(Robotaxi)关键技术分析
萝卜快跑(Robotaxi)关键技术分析
萝卜快跑(百度Apollo旗下自动驾驶出行服务)作为国内领先的自动驾驶出租车(Robotaxi)项目,其核心技术融合了感知、决策、执行、通信、云平台等多方面技术,旨在实现安全、高效的无人驾驶出行服务。以下是其关键技术的详细分析: 1. 感
2025-05-22
下一篇 
Canal:MySQL 实时数据同步的核心解决方案
Canal:MySQL 实时数据同步的核心解决方案
1. Canal 是什么?Canal(意为“运河”)是阿里巴巴开源的一款基于 MySQL 增量日志解析 的数据同步工具,主要用于实现 MySQL 实库到其他数据存储系统(如 Elasticsearch、Kafka、HBase、Redis 等
2025-04-11

MySQL 生成列(Generated Column),也称为虚拟列,是一种特殊类型的列,其值由其他列的值通过表达式计算得出,而不是直接存储在表中。

基本概念

生成列分为两种类型:

  1. 虚拟列(VIRTUAL):值在查询时动态计算,不占用存储空间
  2. 存储列(STORED):值在插入或更新时计算并存储,占用存储空间

特点

  1. 表达式支持:可以使用大多数MySQL表达式,包括算术运算、函数调用、CASE表达式等
  2. 约束:虚拟列可以有NOT NULL约束,但不能有DEFAULT或AUTO_INCREMENT约束
  3. 索引:存储列可以建立索引,虚拟列也可以(MySQL 5.7.6+)
  4. 外键:不能作为外键引用

使用场景

  1. 简化查询:避免在查询中重复计算
  2. 数据一致性:确保派生值始终与源数据一致
  3. 性能优化:对存储列建立索引可以提高查询性能

创建生成列

1
2
3
4
5
6
7
8
CREATE TABLE employees (
id INT PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
full_name VARCHAR(100) GENERATED ALWAYS AS (CONCAT(first_name, ' ', last_name)) VIRTUAL,
salary DECIMAL(10,2),
annual_salary DECIMAL(10,2) GENERATED ALWAYS AS (salary * 12) STORED
);

修改生成列

1
2
ALTER TABLE employees 
MODIFY COLUMN full_name VARCHAR(100) GENERATED ALWAYS AS (CONCAT(first_name, ' ', last_name, ' (Employee)')) VIRTUAL;

删除生成列

1
ALTER TABLE employees DROP COLUMN full_name;

注意事项

• 虚拟列不能引用其他虚拟列

• 在MySQL 5.7中,只有存储列可以有索引

• 在MySQL 8.0中,虚拟列也可以有索引

• 虚拟列的值在查询时计算,可能影响性能(特别是复杂表达式)

PHP laravel中如何查找指定表中的生成列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 获取指定表的生成列
* @param string $tableName
* @return array
*/
public static function getGeneratedColumns(string $tableName): array
{
$database = env("DB_DATABASE");
$cacheKey = "db_generated_columns_{$database}_{$tableName}";
return RedisService::cacheObject($cacheKey, [], function () use ($tableName, $database) {
try {
return DB::table('information_schema.COLUMNS')
->where('TABLE_SCHEMA', $database)
->where('TABLE_NAME', $tableName)
->whereIn('EXTRA', [
'VIRTUAL GENERATED',
'STORED GENERATED',
'auto_increment', // 自增列
'DEFAULT_GENERATED',
'DEFAULT_GENERATED on update CURRENT_TIMESTAMP', // 时间戳列
'on update CURRENT_TIMESTAMP' // 时间戳列
])
->select('COLUMN_NAME')
->pluck('COLUMN_NAME')
->toArray();
} catch (\Throwable $e) {
Log::error("Failed to get generated columns for table {$tableName} in database {$database}: " . $e->getMessage());
return [];
}
});
}

说明

虚拟列的内容不能修改,如果直接修改会报错,提示The value specified for generated column 'sc_gmv' in table 'sc_storage_game' is not allowed.

总结

MySQL 生成列为数据库设计提供了强大的功能,可以简化应用逻辑、提高数据一致性并优化查询性能。在 Laravel 中,通过封装服务类并结合缓存机制,可以高效地管理和使用生成列。开发者应根据具体业务场景选择虚拟列或存储列,并注意相关限制和最佳实践。

通过合理使用生成列,可以显著提升数据库设计的灵活性和性能,同时保持代码的简洁性和可维护性。


文章作者: Crazy Boy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Crazy Boy !
评 论
 上一篇
萝卜快跑(Robotaxi)关键技术分析
萝卜快跑(Robotaxi)关键技术分析
萝卜快跑(百度Apollo旗下自动驾驶出行服务)作为国内领先的自动驾驶出租车(Robotaxi)项目,其核心技术融合了感知、决策、执行、通信、云平台等多方面技术,旨在实现安全、高效的无人驾驶出行服务。以下是其关键技术的详细分析: 1. 感
2025-05-22
下一篇 
Canal:MySQL 实时数据同步的核心解决方案
Canal:MySQL 实时数据同步的核心解决方案
1. Canal 是什么?Canal(意为“运河”)是阿里巴巴开源的一款基于 MySQL 增量日志解析 的数据同步工具,主要用于实现 MySQL 实库到其他数据存储系统(如 Elasticsearch、Kafka、HBase、Redis 等
2025-04-11
  目录
  目录
hexo