MySQL虚拟字段,因不是必用且耗算力。所以是冷门的存在,很多开发者都会忽略它。当然存在就有价值,花时间整理了相关知识点。
ALTER TABLE `表名` ADD COLUMN `虚拟字段名` 值类型 GENERATED ALWAYS AS (表达式) VIRTUAL或STORED NOT NULL;
CREATE TABLE `test` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表主键id',
`num` int NOT NULL COMMENT '存储数字',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `test` ADD COLUMN `num_v` int GENERATED ALWAYS AS (num + 1) VIRTUAL NOT NULL AFTER `num`;
INSERT INTO `test` (`num`) VALUES (1)
INSERT INTO `test` (`num`) VALUES (2)
id num num_v
1 1 2
2 2 3
ALTER TABLE `表名` DROP COLUMN `虚拟字段名称`;
ALTER TABLE `表名` MODIFY COLUMN `虚拟字段` int GENERATED ALWAYS AS (表达式) VIRTUAL或STORED NOT NULL;
show create table 表名
desc 表名
建表
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表id',
`str` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '测试用字符串',
`str_reverse_v` varchar(20) COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (reverse(`str`)) VIRTUAL NOT NULL COMMENT '反转字符串,虚拟字段',
`str_upper_s` varchar(20) COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (upper(`str`)) STORED NOT NULL COMMENT '大写,生成字段',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
新增两条数据
INSERT INTO `test` (`str`) VALUES ('abc');
INSERT INTO `test` (`str`) VALUES ('xyz');
尝试将两个虚拟字段添加索引,没发现报错
ALTER TABLE `test` ADD INDEX(`str_reverse_v`), ADD INDEX(`str_upper_s`);
用explain分析,发现确实用到了索引
explain SELECT str_reverse_v FROM `test` where str_reverse_v = 'mn';
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE test ref str_reverse_v str_reverse_v 82 const 1 100.00 Using index
explain SELECT str_upper_s FROM `test` where str_upper_s = 'mn';
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE test ref str_upper_s str_upper_s 82 const 1 100.00 Using index
CREATE TABLE `test` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表主键id',
`ip` bigint NOT NULL DEFAULT '0' COMMENT 'IPV4 数字格式',
`ip_v` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (inet_ntoa(`ip`)) STORED NOT NULL COMMENT 'IPV4 字符串格式',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `test` (`ip`) VALUES (2130706433);
INSERT INTO `test` (`ip`) VALUES (3232235776);
select * from test
id ip ip_v
1 2130706433 127.0.0.1
2 3232235776 192.168.1.0
CREATE TABLE `test` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表主键id',
`user_info` json NOT NULL COMMENT '用户信息',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
假设要插入一条多层级的json数据,如下
{
"name": "张三",
"gender": "男",
"age": 8,
"birthplace": "北京市",
"occupation": "学生",
"hobbies": [
"打篮球",
"读书"
],
"contact": {
"phone": "18888888888",
"email": "zhangsan@example.com"
},
"examination": [
{
"subject": "语文",
"score": 80
},
{
"subject": "数学",
"score": 80
},
{
"subject": "英文",
"score": 80
}
]
}
INSERT INTO `test` (`id`, `user_info`) VALUES (1, '{"age": 8, "name": "张三", "gender": "男", "contact": {"email": "zhangsan@example.com", "phone": "18888888888"}, "hobbies": ["打篮球", "读书"], "birthplace": "北京市", "occupation": "学生", "examination": [{"score": 80, "subject": "语文"}, {"score": 80, "subject": "数学"}, {"score": 80, "subject": "英文"}]}');
可需求是就像查看这个学生考了哪些科目,其它数据都不重要
此时就需要定向取值,若取单条,可用
SELECT json_unquote(json_extract(`user_info`,_utf8mb4'$.examination[*].subject')) as subjects FROM `test`
若是多条,可以新建一个虚拟字段,可以很直观的展示考取了哪些科目
ALTER TABLE `test`
ADD COLUMN `subjects` json AS (json_unquote(json_extract(`user_info`,_utf8mb4'$.examination[*].subject'))) STORED NOT NULL AFTER `user_info`;
select id, subjects from test
id subjects
1 ["语文", "数学", "英文"]
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表id',
`timestamp` int(11) NOT NULL COMMENT '时间戳',
`date_time` datetime GENERATED ALWAYS AS (from_unixtime(`timestamp`)) STORED COMMENT '格式化时间戳 存储字段',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `test` (`timestamp`) VALUES (1700000000);
select * from test
id timestamp date_time
1 1700000000 2023-11-15 06:13:20
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表id',
`age` int(11) NOT NULL COMMENT '年龄',
`age_v` varchar(2) COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS ((case when (`age`
参与评论
手机查看
返回顶部