IT评测·应用市场-qidao123.com

标题: 5千字总结冷门的MySQL虚拟字段(虚拟列) [打印本页]

作者: 刘俊凯    时间: 2025-3-24 06:24
标题: 5千字总结冷门的MySQL虚拟字段(虚拟列)
MySQL虚拟字段,因不是必用且耗算力。所以是冷门的存在,许多开发者都会忽略它。当然存在就有价值,花时间整理了相关知识点。
MySQL虚拟字段(或叫虚拟列)



  1. ALTER TABLE `表名` ADD COLUMN `虚拟字段名` 值类型 GENERATED ALWAYS AS (表达式) VIRTUAL或STORED NOT NULL;
复制代码
  1. CREATE TABLE `test` (
  2.   `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表主键id',
  3.   `num` int NOT NULL COMMENT '存储数字',
  4.   PRIMARY KEY (`id`)
  5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
复制代码
  1. ALTER TABLE `test` ADD COLUMN `num_v` int GENERATED ALWAYS AS (num + 1) VIRTUAL NOT NULL AFTER `num`;
复制代码
  1. INSERT INTO `test` (`num`) VALUES (1)
  2. INSERT INTO `test` (`num`) VALUES (2)
复制代码
  1. id        num        num_v
  2. 1        1        2
  3. 2        2        3
复制代码

  1. ALTER TABLE `表名`  DROP COLUMN `虚拟字段名称`;
复制代码

  1. ALTER TABLE `表名` MODIFY COLUMN `虚拟字段` int GENERATED ALWAYS AS (表达式) VIRTUAL或STORED NOT NULL;
复制代码

  1. show create table 表名
  2. desc 表名
复制代码
虚拟字段使用束缚

虚拟、天生字段对索引的支持

  1. 建表
  2. CREATE TABLE `test` (
  3.   `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表id',
  4.   `str` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '测试用字符串',
  5.   `str_reverse_v` varchar(20) COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (reverse(`str`)) VIRTUAL NOT NULL COMMENT '反转字符串,虚拟字段',
  6.   `str_upper_s` varchar(20) COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (upper(`str`)) STORED NOT NULL COMMENT '大写,生成字段',
  7.   PRIMARY KEY (`id`)
  8. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  9. 新增两条数据
  10. INSERT INTO `test` (`str`) VALUES ('abc');
  11. INSERT INTO `test` (`str`) VALUES ('xyz');
  12. 尝试将两个虚拟字段添加索引,没发现报错
  13. ALTER TABLE `test` ADD INDEX(`str_reverse_v`), ADD INDEX(`str_upper_s`);
  14. 用explain分析,发现确实用到了索引
  15. explain SELECT str_reverse_v FROM `test` where str_reverse_v = 'mn';
  16. id        select_type        table        partitions        type        possible_keys        key        key_len        ref        rows        filtered        Extra
  17. 1        SIMPLE        test                ref        str_reverse_v        str_reverse_v        82        const        1        100.00        Using index
  18. explain SELECT str_upper_s FROM `test` where str_upper_s = 'mn';
  19. id        select_type        table        partitions        type        possible_keys        key        key_len        ref        rows        filtered        Extra
  20. 1        SIMPLE        test                ref        str_upper_s        str_upper_s        82        const        1        100.00        Using index
复制代码
常见用法举例

  1. CREATE TABLE `test` (
  2.   `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表主键id',
  3.   `ip` bigint NOT NULL DEFAULT '0' COMMENT 'IPV4 数字格式',
  4.   `ip_v` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (inet_ntoa(`ip`)) STORED NOT NULL COMMENT 'IPV4 字符串格式',
  5.   PRIMARY KEY (`id`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  7. INSERT INTO `test` (`ip`) VALUES (2130706433);
  8. INSERT INTO `test` (`ip`) VALUES (3232235776);
  9. select * from test
  10. id        ip                ip_v
  11. 1        2130706433        127.0.0.1
  12. 2        3232235776        192.168.1.0
复制代码
  1. CREATE TABLE `test` (
  2.   `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表主键id',
  3.   `user_info` json NOT NULL COMMENT '用户信息',
  4.   PRIMARY KEY (`id`)
  5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  6. 假设要插入一条多层级的json数据,如下
  7. {
  8.     "name": "张三",
  9.     "gender": "男",
  10.     "age": 8,
  11.     "birthplace": "北京市",
  12.     "occupation": "学生",
  13.     "hobbies": [
  14.         "打篮球",
  15.         "读书"
  16.     ],
  17.     "contact": {
  18.         "phone": "18888888888",
  19.         "email": "zhangsan@example.com"
  20.     },
  21.     "examination": [
  22.         {
  23.             "subject": "语文",
  24.             "score": 80
  25.         },
  26.         {
  27.             "subject": "数学",
  28.             "score": 80
  29.         },
  30.         {
  31.             "subject": "英文",
  32.             "score": 80
  33.         }
  34.     ]
  35. }
  36. 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": "英文"}]}');
  37. 可需求是就像查看这个学生考了哪些科目,其它数据都不重要
  38. 此时就需要定向取值,若取单条,可用
  39. SELECT json_unquote(json_extract(`user_info`,_utf8mb4'$.examination[*].subject')) as subjects FROM `test`
  40. 若是多条,可以新建一个虚拟字段,可以很直观的展示考取了哪些科目
  41. ALTER TABLE `test`
  42. ADD COLUMN `subjects` json AS (json_unquote(json_extract(`user_info`,_utf8mb4'$.examination[*].subject'))) STORED NOT NULL AFTER `user_info`;
  43. select id, subjects from test
  44. id        subjects
  45. 1        ["语文", "数学", "英文"]
复制代码
  1. CREATE TABLE `test` (
  2.   `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表id',
  3.   `timestamp` int(11) NOT NULL COMMENT '时间戳',
  4.   `date_time` datetime GENERATED ALWAYS AS (from_unixtime(`timestamp`)) STORED COMMENT '格式化时间戳 存储字段',
  5.   PRIMARY KEY (`id`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  7. INSERT INTO `test` (`timestamp`) VALUES (1700000000);
  8. select * from test
  9. id        timestamp        date_time
  10. 1        1700000000        2023-11-15 06:13:20
复制代码
  1. CREATE TABLE `test` (
  2.   `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '测试表id',
  3.   `age` int(11) NOT NULL COMMENT '年龄',
  4.   `age_v` varchar(2) COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS ((case when (`age` < 12) then '儿童' when (`age` between 12 and 18) then '少年' when (`age` between 19 and 40) then '青年' when (`age` between 41 and 60) then '壮年' else '老年' end)) STORED NOT NULL COMMENT '年龄可视化判断',
  5.   PRIMARY KEY (`id`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  7. INSERT INTO `test` (`age`) VALUES (11);
  8. INSERT INTO `test` (`age`) VALUES (16);
  9. INSERT INTO `test` (`age`) VALUES (25);
  10. INSERT INTO `test` (`age`) VALUES (53);
  11. INSERT INTO `test` (`age`) VALUES (65);
  12. SELECT * FROM test
  13. id        age        age_v
  14. 1        11        儿童
  15. 2        16        少年
  16. 3        25        青年
  17. 4        53        壮年
  18. 5        65        老年
复制代码

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4