Lecture
Introduction:
What is a virtual column?
Syntax:
The syntax for adding a new virtual column,
==> Alter table table_name add column column_name generated always as column_name;
Example :
Alter the contacts table to add a column that is always generated as mydbops_test virtual / stored.
GENERATED ALWAYS - indicates that the column is a generated column.
VIRTUAL - column values are not stored, but they are evaluated when rows are read.
STORED - column values are evaluated and stored when rows are inserted or updated.
Case 1 (using concat):
For example, we have the mydbops_lab_test table structure as shown below,
mysql> create table mydbops_lab_test (id int (11) NOT NULL AUTO_INCREMENT primary key, firstname varchar (20), lastname varchar (20), full_name char (41) GENERATED ALWAYS AS (concat (firstname, '', lastname)), email_id varchar (25)); Query OK, 0 rows affected (0.40 sec)
mysql> desc mydbops_lab_test; + ----------- + ------------- + ------ + ----- + --------- + ------------------- + | Field | Type | Null | Key | Default | Extra | + ----------- + ------------- + ------ + ----- + --------- + ------------------- + | id | int (11) | NO | PRI | NULL | auto_increment | | firstname | varchar (20) | YES | | NULL | | | lastname | varchar (20) | YES | | NULL | | | full_name | char (41) | YES | | NULL | VIRTUAL GENERATED | | email_id | varchar (25) | YES | | NULL | | + ----------- + ------------- + ------ + ----- + --------- + ------------------- + 5 rows in set (0.00 sec)
We need to test the full_name column, so let's populate a few rows in the contacts table.
mysql> select * from mydbops_lab_test; + ---- + ----------- + ---------- + -------------- + ------ ----------- + | id | firstname | lastname | full_name | email_id | + ---- + ----------- + ---------- + -------------- + ------ ----------- + | 1 | John | Rubin | John Rubin | rubin@gmail.com | | 2 | Mark | Henry | Mark Henry | mark@gmail.com | | 3 | Peter | Parker | Peter Parker | peter@yahoo.com | | 4 | Jim | Rose | Jim Rose | jim@outlook.com | + ---- + ----------- + ---------- + -------------- + ------ ----------- + 4 rows in set (0.00 sec)
Adding a virtual column to an existing table:
mysql> ALTER TABLE v_column ADD full_name char (41) GENERATED ALWAYS AS (concat (firstname, '', lastname)) VIRTUAL NOT NULL; Query OK, 0 rows affected (0.35 sec) Records: 0 Duplicates: 0 Warnings: 0
Case 2 (using difference):
mysql> create table mydbops_lab_test_1 (id int (11) NOT NULL AUTO_INCREMENT primary key, Total_cost float (9,4), Discount float (9,4), Balance_amount float (12,6) GENERATED ALWAYS AS (Total_cost - Discount), email_id varchar (25), firstname 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 | | | Discount | 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> select id, name, Total_cost, Balance_amount from mydbops_lab_test_1 where Balance_amount <2000 order by Balance_amount desc;
+ ---- + -------- + ------------ + ---------------- + | id | name | Total_cost | Balance_amount | + ---- + -------- + ------------ + ---------------- + | 1 | rose | 2000.0000 | 1949.109985 | | 5 | raj | 810.1100 | 798.209961 | | 4 | Kevin | 900.0000 | 579.000000 | | 9 | suresh | 677.1000 | 457.099976 | | 3 | Jim | 100.0000 | 71.000000 | | 8 | bell | 41.9700 | 19.970001 | + ---- + -------- + ------------ + ---------------- + 6 rows in set (0.00 sec)
Indexing virtual columns:
Example:
Here I've added an index for the virtual generated column (Balance_amount).
Syntax:
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, `Discount` float (9,4) DEFAULT NULL, `Balance_amount` float (12,6) GENERATED ALWAYS AS ((`Total_cost` - `Discount`)) 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)
Advantages:
Disadvantages:
Key points to remember:
Generated column expressions are subject to a few rules:
The Select portion of the statement cannot assign values to generated columns in the destination table.
Comments