MySQL中支持生成列,生成列的值是根据列定义中包含的表达式计算的。

一个简单的例子来认识生成列!

CREATE TABLE triangle(
sidea DOUBLE,
sideb DOUBLE,
sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb))
); INSERT INTO triangle(sidea, sideb) VALUES(3,4),(6,8),(5,12); mysql> select * from triangle; #插入数值的时候并没有插入c的值,但是查询的时候,还是有了c值
+-------+-------+-------+
| sidea | sideb | sidec |
+-------+-------+-------+
| 3 | 4 | 5 |
| 6 | 8 | 10 |
| 5 | 12 | 13 |
+-------+-------+-------+
3 rows in set (0.00 sec) mysql>

生成列中的值,是根据生成列的定义计算出来的!

生成列的定义如下:

col_name data_type [GENERATED ALWAYS] AS (expression)
[VIRTUAL | STORED] [NOT NULL | NULL]
[UNIQUE [KEY]] [[PRIMARY] KEY]
[COMMENT 'string']
#AS表达式表示生成列并用于计算生成列的表达式。As之前的GENERATED ALWAYS可以让生成列的性质更明确(应该没什么作用,反正是可以省略的)!
#VIRTUAL | STORED 关键字表示列值的存储方式
  • VIRTUAL: 不存储列值,但在读取值之前立即计算此列的数值,虚拟列不占存储空间,innodb支持虚拟列上的二级索引。为默认的存储方式。
  • STORED:插入或更新时,将计算存储列的值,并且占用存储空间。
 生成列的表达式必须遵循以下的规则,否则会报错:
  1. 允许使用字符串,运算符和确定性内置函数。对于给定的相同的数据库,不同连接的用户调用会产生相同的结果,则这个函数时确定的。now()函数就不是确定性函数。
  2. 不允许使用子查询,参数,变量,存储函数(stored functions)和用户自定义的函数。
  3. 生成的列定义可以引用其他生成的列,但只能引用表定义中较早出现的列。生成的列定义可以引用表中的任何基本(非生成)列,无论其定义是早期还是稍后发生。
  4. auto_increment属性不能再生成列的定义中使用。
  5. 一个AUTO_INCREMENT列不能用作在生成的列定义的基柱(An AUTO_INCREMENT column cannot be used as a base column in a generated column definition.)
  6. 从MySQL 5.7.10开始,如果表达式求值导致截断或向函数提供不正确的输入,则 CREATE TABLE语句将以错误终止并拒绝DDL操作

生成列的作用(可能不太准确):

  • 虚拟生成的列可用作简化和统一查询的方法。可以将复杂条件定义为生成列,并从表上的多个查询引用,以确保他们全部使用完全相同的条件。
  • 存储生成的列可以用作物化缓存,用于复杂的条件,这些条件在运行中计算成本很高。
  • 生成列可以模拟功能索引,利用生成列定义功能表达式对其进行索引。例如对JSON数据类型。对于存储的生成列,这种方法缺点是存储两次,一次是生成列的值,另一次是索引。
  • 如果生成的列已编制索引,则优化程序将识别与列定义匹配的查询表达式,并在查询执行期间根据需要使用列中的索引,即使查询未按名称直接引用该列也是如此。

如下一个含有json类型字段的表:

CREATE TABLE json_test (
id INT auto_increment PRIMARY KEY,
userinfo json
); #插入数据 INSERT INTO json_test(userinfo) VALUES('{"name":"libai","address":"china","email":"libai@163.com"}');
INSERT INTO json_test(userinfo) VALUES('{"name":"obama","address":"miguo","email":"libai@gmail.com"}');
INSERT INTO json_test(userinfo) VALUES('{"name":"putin","address":"russia","email":"putin@gmail.com"}'); #

给表中添加生成列

alter table json_test add column user_name varchar(40) generated always  as (userinfo->"$.name") virtual;

#查看表中的数据
mysql> select * from json_test;
+----+--------------------------------------------------------------------+-----------+
| id | userinfo | user_name |
+----+--------------------------------------------------------------------+-----------+
| 1 | {"name": "libai", "email": "libai@163.com", "address": "china"} | "libai" |
| 2 | {"name": "obama", "email": "libai@gmail.com", "address": "miguo"} | "obama" |
| 3 | {"name": "putin", "email": "putin@gmail.com", "address": "russia"} | "putin" |
+----+--------------------------------------------------------------------+-----------+
3 rows in set (0.00 sec) #在表中插入数据user_name列的数值会自动计算,这时候,我们就可以对user_name列添加索引!

mysql中生成列与JSON类型的索引的更多相关文章

  1. MySQL 5.7 使用原生JSON类型

    首先回顾一下JSON的语法规则: 数据在键值对中, 数据由逗号分隔, 花括号保存对象, 方括号保存数组. 按照最简单的形式,可以用下面的JSON表示: {"NAME": " ...

  2. MySQL中TEXT与BLOB字段类型的区别

    这篇文章主要介绍了MySQL中TEXT与BLOB字段类型的区别,本文总结了6大区别,需要的朋友可以参考下   在MySQL中有两个字段类型容易让人感觉混淆,那就是TEXT与BLOB,特别是自己写博客程 ...

  3. 转:JS中生成和解析JSON

    原文地址:JS中生成和解析JSON 1.JS中生成JSON对象的方法: var json = []; var row1 = {}; row1.id= "1"; row1.name ...

  4. [置顶] mysql中的set和enum类型的用法和区别

    mysql中的enum和set其实都是string类型的而且只能在指定的集合里取值,  不同的是set可以取多个值,enum只能取一个值.   CREATE TABLE `20121101_t` ( ...

  5. 使用PowerDesigner创建物理模型并生成SQL语句在MySQL中生成表

    我使用的PowerDesigner的版本为16.5,创建物理模型后,使用PowerDesigner生成的SQL语句,在MySQL中创建表. 1. 打开Power Designer软件,在弹出的欢迎对话 ...

  6. mysql中别名(列别名和表别名)

    1.介绍 使用MySQL别名来提高查询的可读性.MySQL支持两种别名,称为列别名和表别名. 有时,列的名称是一些表达式,使查询的输出很难理解.要给列一个描述性名称,可以使用列别名.用法: SELEC ...

  7. 关于MySQL中的三种日期类型

    Mysql中我们经常用来存储日期的数据类型有三种:Date.Datetime.Timestamp. Date数据类型用来存储没有时间的日期.Mysql获取和显示这个类型的格式为"YYYY-M ...

  8. mysql中几个日期时间类型之间的区别和使用

    MySQL中有如下几个时间类型:date.time.datetime.timestamp.year MySQL数据类型           含义 date                     只存 ...

  9. MySQL 中NULL和空值的区别,索引列可以有空值或者null吗?

    空值跟null的区别.mysql官方: “NULL columns require additional space in the row to record whether their values ...

随机推荐

  1. HTML - 分页效果布局

    <p class="jcFY"> 显示 <select name="" id=""> <option valu ...

  2. 几种减小javascript对性能影响的方法

    1.将所有的script标签放在页面的底部,body的结束标签</body>之前. 2.将脚本打包,script标签越少,请求数就越少,加载速度加快,相应的响应时间变短. 3.使用非阻塞的 ...

  3. Hibernate插入、查询、删除操作 HQL

    Hibernate的所有的操作都是通过Session完成的. 基本步骤如下: 1:通过配置文件得到SessionFactory: SessionFactory sessionFactory=new C ...

  4. 微信开发(2):微信js sdk分享朋友圈,朋友,获取config接口注入权限验证(转)

    进行微信开发已经一阵子了,从最初的什么也不懂,到微信授权登录,分享,更改底部菜单,素材管理,等. 今天记录一下微信jssdk 的分享给朋友的功能,获取config接口注入. 官方文档走一下简单说:四步 ...

  5. java实现创建临时文件然后在程序退出时自动删除文件(转)

    这篇文章主要介绍了java实现创建临时文件然后在程序退出时自动删除文件,从个人项目中提取出来的,小伙伴们可以直接拿走使用. 通过java的File类创建临时文件,然后在程序退出时自动删除临时文件.下面 ...

  6. Python使用logging来记录日志

    #encoding:utf-8 import logging.config from logging.handlers import RotatingFileHandler import Config ...

  7. Python爬虫scrapy-redis分布式实例(一)

    目标任务:将之前新浪网的Scrapy爬虫项目,修改为基于RedisSpider类的scrapy-redis分布式爬虫项目,将数据存入redis数据库. 一.item文件,和之前项目一样不需要改变 # ...

  8. 数字签名中公钥和私钥是什么?对称加密与非对称加密,以及RSA的原理

    http://baijiahao.baidu.com/s?id=1581684919791448393&wfr=spider&for=pc https://blog.csdn.net/ ...

  9. Django中URL的解析和反查

    add by zhj: 如果想用reverse(namespace1:namespace2:...:namespaceN:name)反查url(注意:用reverse('polls:index')方法 ...

  10. 如何在linux下安装jdk并运行java程序

    一.进入root 大家可以看到我这里用的是CentOS 6.5 系统 二.测试网络与YUM是否可用 1.测试网络 ping www.baidu.com,如下图就是通了 参考: 一.JDK安装1.lin ...