MySQL生成列

2019-10-16 22:56:54

在本教學中,您將學習如何使用MySQL生成的列來儲存從表示式或其他列計算的資料。

MySQL生成列簡介

建立新表時,可以在CREATE TABLE語句中指定表列。 然後,使用INSERTUPDATEDELETE語句直接修改表列中的資料。

MySQL 5.7引入了一個名為生成列的新功能。它之所以叫作生成列,因為此列中的資料是基於預定義的表示式或從其他列計算的。

例如,假設有以下結構的一個contacts表:

CREATE TABLE IF NOT EXISTS contacts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL
);

要獲取聯絡人的全名,請使用CONCAT()函式,如下所示:

SELECT 
    id, CONCAT(first_name, ' ', last_name), email
FROM
    contacts;

這不是最優的查詢。

通過使用MySQL生成的列,可以重新建立contacts表,如下所示:

DROP TABLE IF EXISTS contacts;

CREATE TABLE contacts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    fullname varchar(101) GENERATED ALWAYS AS (CONCAT(first_name,' ',last_name)),
    email VARCHAR(100) NOT NULL
);

GENERATED ALWAYS as(expression)是建立生成列的語法。

要測試「全名」列,請在contacts表中插入一行。

INSERT INTO contacts(first_name,last_name, email)
VALUES('john','doe','[email protected]');

現在,可以從contacts表中查詢資料。

當從contacts表中查詢資料時,fullname列中的值將立即計算。

MySQL提供了兩種型別的生成列:儲存和虛擬。每次讀取資料時,虛擬列都將在執行中計算,而儲存的列在資料更新時被物理計算和儲存。

基於此定義,上述範例中的fullname列是虛擬列。

MySQL生成列的語法

定義生成列的語法如下:

column_name data_type [GENERATED ALWAYS] AS (expression)
   [VIRTUAL | STORED] [UNIQUE [KEY]]

首先,指定列名及其資料型別。

接下來,新增GENERATED ALWAYS子句以指示列是生成的列。

然後,通過使用相應的選項來指示生成列的型別:VIRTUALSTORED。 預設情況下,如果未明確指定生成列的型別,MySQL將使用VIRTUAL

之後,在AS關鍵字後面的大括號內指定表示式。 該表示式可以包含文字,內建函式,無引數,操作符或對同一表中任何列的參照。 如果你使用一個函式,它必須是標量和確定性的。

最後,如果生成的列被儲存,可以為它定義一個唯一約束

MySQL儲存列範例

我們來看一下範例資料庫(yiibaidb)中的products表。

mysql> desc products;
+--------------------+---------------+------+-----+---------+-------+
| Field              | Type          | Null | Key | Default | Extra |
+--------------------+---------------+------+-----+---------+-------+
| productCode        | varchar(15)   | NO   | PRI |         |       |
| productName        | varchar(70)   | NO   |     | NULL    |       |
| productLine        | varchar(50)   | NO   | MUL | NULL    |       |
| productScale       | varchar(10)   | NO   |     | NULL    |       |
| productVendor      | varchar(50)   | NO   |     | NULL    |       |
| productDescription | text          | NO   |     | NULL    |       |
| quantityInStock    | smallint(6)   | NO   |     | NULL    |       |
| buyPrice           | decimal(10,2) | NO   |     | NULL    |       |
| MSRP               | decimal(10,2) | NO   |     | NULL    |       |
+--------------------+---------------+------+-----+---------+-------+
9 rows in set

使用quantityInStockbuyPrice列的資料,通過以下表示式計算每個SKU的股票值:

quantityInStock * buyPrice

但是,可以使用以下ALTER TABLE … ADD COLUMN語句將名為stock_value的儲存的生成列新增到products表:

ALTER TABLE products
ADD COLUMN stockValue DOUBLE 
GENERATED ALWAYS AS (buyprice*quantityinstock) STORED;

通常,ALTER TABLE語句需要完整的表重建,因此,如果更改大表是耗時的。 但是,虛擬列並非如此。

現在,我們可以直接從products表中查詢庫存值。

SELECT 
    productName, ROUND(stockValue, 2) AS stock_value
FROM
    products;

執行上面查詢語句,得到以下結果 -

+---------------------------------------------+-------------+
| productName                                 | stock_value |
+---------------------------------------------+-------------+
| 1969 Harley Davidson Ultimate Chopper       |   387209.73 |
| 1952 Alpine Renault 1300                    |   720126.90 |
| 1996 Moto Guzzi 1100i                       |   457058.75 |
| 2003 Harley-Davidson Eagle Drag Bike        |   508073.64 |
| 1972 Alfa Romeo GTA                         |   278631.36 |
| 1962 LanciaA Delta 16V                      |   702325.22 |
| 1968 Ford Mustang                           |     6483.12 |
|************** 省略了一大波資料 ****************************|
| The Queen Mary                              |   272869.44 |
| American Airlines: MD-11S                   |   319901.40 |
| Boeing X-32A JSF                            |   159163.89 |
| Pont Yacht                                  |    13786.20 |
+---------------------------------------------+-------------+
110 rows in set

在本教學中,我們向您介紹了MySQL生成的列以儲存從表示式或其他列計算的資料。