最近写个搬数据脚本,发现报了个这样的错
3105, "The value specified for generated column '某字段' in table '某表' is not allowed."
研究后发现该字段是自动生成的(generated column),主动去添加肯定会报错。解决方案就是增、改时别动这个字段
参考:https://stackoverflow.com/questions/50667827/update-a-virtual-generated-column/50668208
延申
作为不怎么懂sql的前端,查阅了一波资料来了解数据库生成字段generated column(virtual column)的机制,也算了解一波mysql
mysql > create table mydbops_lab_test_1
(id int(11) NOT NULL AUTO_INCREMENT primary key,
Total_cost float(9,4),
Expensive float(9,4),
Balance_amount float(12,6) GENERATED ALWAYS AS (Total_cost - Expensive),
email_id varchar(25),
name varchar(30));
Query OK, 0 rows affected (0.34 sec)
先上一波代码,上述代码中的Balance_amount
字段就属于生成字段
GENERATED ALWAYS
语句代表该字段是生成字段,其有两种模式:
VIRTUAL
:只会在读取的时候拿到,不会存为字段
STORED
:存为字段
定义的语法如代码所示,个人觉得需要注意的主要有两点:
1.子查询、变量、库函数和你自己写的函数不能用在表达式里
2.你可以用其他的生成字段来计算新的生成字段,但要注意你使用生成的字段要在前面声明过
另外说下生成字段主要的应用场景:你有一些复杂的查询(或者是常写的查询),此时写个生成字段,相当于进行一个封装;或者你的某些字段是JSON,查起来不方便。
文章有提到生成字段的缺点:生成字段会在column,index里面存两遍;将生成字段作为索引会带来一些问题(不是很懂MySQL,可自己读文章)
更多样例:
mysql > create table mydbops_lab_test_1
(id int(11) NOT NULL AUTO_INCREMENT primary key,
Total_cost float(9,4),
Expensive float(9,4),
Balance_amount float(12,6) GENERATED ALWAYS AS (Total_cost - Expensive),
email_id varchar(25),
name varchar(30));
Query OK, 0 rows affected (0.34 sec)
mysql> desc mydbops_lab_test_1;
+----------------+-------------+------+-----+---------+-------------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| Total_cost | float(9,4) | YES | | NULL | |
| Expensive | float(9,4) | YES | | NULL | |
| Balance_amount | float(12,6)| YES | | NULL | VIRTUAL GENERATED |
| email_id | varchar(25)| YES | | NULL | |
| name | varchar(30)| NO | | NULL | |
+----------------+-------------+------+-----+---------+-------------------+
6 rows in set (0.00 sec)
mysql> alter table mydbops_lab_test_1 add index idx_Balance_amount(Balance_amount);
Query OK, 0 rows affected (0.33 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table mydbops_lab_test_1\G
*************************** 1. row ***************************
Table: mydbops_lab_test_1
Create Table: CREATE TABLE `mydbops_lab_test_1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Total_cost` float(9,4) DEFAULT NULL,
`Expensive` float(9,4) DEFAULT NULL,
`Balance_amount` float(12,6) GENERATED ALWAYS AS ((`Total_cost` - `Expensive`)) VIRTUAL,
`email_id` varchar(25) DEFAULT NULL,
`name` varchar(30) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_Balance_amount` (`Balance_amount`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
参考:https://mydbops.wordpress.com/2017/07/19/virtual-columns-in-mysql-and-use-cases/