MySQL8.0新特性CTE(Common Table Expression)

2020-12-23 偏執的IT工匠

CTE(Common Table Expression)可以認為是派生表(derived table)的替代,在一定程度上,CTE簡化了複雜的join查詢和子查詢,提高了SQL的可讀性和執行性能。CTE是ANSI SQL 99標準的一部分,在MySQL 8.0.1版本被引入。

原文地址:https://mytecdb.com/blogDetail.php?id=75

1. CTE優勢

查詢語句的可讀性更好在一個查詢中,可以被引用多次能夠連接多個CTE能夠創建遞歸查詢能夠提高SQL執行性能能夠有效地替代視圖2. 如何創建和使用CTE

CTE類似於使用子查詢時的派生表,但是CTE的定義不在SQL主體中,而是提到SQL最前端,聲明CTE的需要使用語法WITH

2.1 CTE的使用

先看一個派生表實現的例子:

使用CTE改寫後,SQL變成這樣:

CTE的語法也比較簡單,在SQL主體查詢之前,使用WITH語法,定義一個或者多個CTE,然後就可以在查詢SQL的主體中引用一次或多次CTE,可以把CTE看成是一類提前物化的臨時表,以便於查詢主體引用。

2.2 為CTE指定具體的欄位名稱

使用圓括號為CTE指定欄位名稱,如下eur_name和eur_population為CTE的欄位:

2.3 CTE也可以被用作數據源來更新其他表

CTE可以作為數據源,來更新或者刪除其他表,如下:

2.4 CTE也可以用於insert ... select 語句

2.5 CTE作為提前物化的臨時表

定義多個CTE,作為提前物化的臨時表,在主查詢裡面可以多次引用這些臨時表。如下:

2.6 CTE的可見性

下面兩個例子,第一個例子中cte對於頂層SELECT可見,第二個例子中,cte對頂層SELECT不可見。為了避免這種不可見的問題,通常將CTE定義在最前面,以便能夠在查詢主體的任何地方都能引用到CTE。

2.7 CTE引用鏈

如果在一個查詢中創建多個CTE,可能會出現一個CTE引用前一個CTE,導致CTE引用鏈的產生。下面這個例子展示了CTE引用鏈:

上述SQL如果使用派生表的方式改寫,也將是非常龐大和複雜的。

2.8 使用CTE代替視圖

如果你的用戶沒有權限創建視圖,而同時又有需要使用視圖,不妨試試CTE來代替視圖。

視圖改寫為CTE,如下:

使用CTE代替視圖能夠有效提高執行效率,在本案例中,視圖的執行時間大概是0.0097秒,而CTE大概是0.0054秒,CTE更快,因為只需要一次物化臨時表,可以被多次引用。

3. 總結

在MySQL 8.0 中引入CTE新特性,在大多數場景下,能夠簡化SQL,提高可讀性,同時也能使用CTE代替視圖,提高整體性能。另外CTE也能實現遞歸查詢,下一篇文章將詳細介紹。

本文譯自:https://www.percona.com/blog/2020/02/10/introduction-to-mysql-8-0-common-table-expressions-part-1/

相關焦點

  • mysql 矩陣類型專題及常見問題 - CSDN
    bytes極大整數值FLOAT4 bytes單精度 浮點數值DOUBLE8 bytes雙精度 浮點數值DECIMAL對DECIMAL(M,D) ,如果M>D,為M+2否則為D+2小數值字符串類型0-255 bytes定長字符串VARCHAR0-65535 bytes變長字符串TINYBLOB0-255 bytes不超過 255 個字符的二進位字符串TINYTEXT0-255 bytes短文本字符串
  • MySQL 數據校驗工具-愛可生|mysql|perl|伺服器|node01_網易訂閱
    [root@node01 ~]# sysbench /usr/share/sysbench/oltp_read_write.lua --mysql-host=10.186.63.82 \  --mysql-port=4380 --mysql-user=gengjin --mysql-password=123 --mysql-db=test \  --table-size
  • MySQL 大量 Opening tables 案例分析-愛可生
    :475),TTASEventMutex::wait(ut0mutex.ic:89),spin_and_try_lock(ib0mutex.h:850),enter(ib0mutex.h:850),PolicyMutex  (ib0mutex.h:850),dict_table_open_on_name(dict0dict.cc:1238),ha_innobase::open_dict_table
  • MYSQL SQL巡檢腳本
    #where DATA_TYPE in ('enum','set','bit','binary') #-- and table_schema not in ('information_schema','mysql','performance_schema','sys')#and table_schema=@dbname#order by table_name;
  • 技術分享 | MySQL 閃回工具 MyFlash
    6 |  | 7 |  | 8 |  | 9 |  | 10 |  +-+  10 rows in set (0.00 sec)  mysql> checksum table d1.t1;  +--+--+  | Table | Checksum
  • Java程式設計師必須知道的MySQL基本語法
    key7、 查看表結構:describe [表名]8、查看詳細結構:show create table [表名]修改表語句1、修改表名:alter table [舊錶名] rename [新表名]2、修改欄位:alter table [表名] change [舊屬性名] [新的屬性名] [新的屬性類型]3、新增欄位:alter table [表名] add [新屬性名] [新屬性類型]4、刪除欄位:alter table [表名] drop [屬性名]
  • 新手入門MYSQL資料庫命令大全
    一、命令行連接資料庫Windows作業系統進入CMD命令行,進入mysql.exe所在目錄,運行命令mysql.exe -h主機名 -u用戶名 -p密碼注意:參數名與值之間沒有空格 , 如:-h127.0.0.1二、資料庫命令1.
  • MySQL案例:一次詭異的Aborted connection錯誤排查
    localhost || mysql.sys | localhost || root | localhost |+---+-+8 rows in set (0.10 sec)2.使用root用戶登錄資料庫,並設置init_connect參數mysql> set global init_connect
  • MySql8.0.22詳細安裝與問題解決
    **第一步:首先下載安裝包,官網下載(我當時最新的是8.0.22):**https://dev.mysql.com/downloads/mysql/**第二步:配置環境變量Path,地址就是你的解壓路徑:****第三步:按照網上常見的配置就是需要自己新建my.ini文件和data文件夾了,這時要記住以下兩點:**1.在創建my.ini
  • mysql主從配置詳細教程
    配置文件,做如下操作:註:mysql安裝方式的不同會導致mysql的配置文件的位置不一樣,大家要根據自己的安裝位置來找配置文件vim /etc/mysql/mysql.conf.d/mysqld.cnf[mysqld]bind_address
  • MySQL資料庫常用命令詳解
    創建一個新表的命令為:create table <表名> ( <欄位名1> <類型1> [,..<欄位名n> <類型n>]);例如,建立一個名為student的學生表,表結構信息如下:在終端窗口輸入如下命令:因命令字符比較長,用截圖給出。
  • MySQL的主從備份
    進程讀取主庫的binlog內容存儲到relay log日誌中從庫的SQL進程讀取relay log日誌中內容在從庫中重放MySQL主從配置步驟配置主從資料庫伺服器參數主伺服器配置log_bin = /data/mysql
  • 讓Python幫你搞定MySQL資料庫
    我們在github上下載fifa18球員數據,將這些信息存入到mysql。utf8_general_ci;#選擇資料庫:use fifa18_db;#創建球員表:id,名稱,海報地址,俱樂部,年齡,薪資等,與csv文件對應create table player(id int Primary key auto_increment, player_id int, name char(64), age int, poster char(64),
  • 一千行MySQL學習筆記
    4位元組    bigint        8位元組    int(M)    M表示總位數    - 默認存在符號位,unsigned 屬性修改    - 顯示寬度,如果某個數不夠定義欄位時設置的位數,則前面以0補填,zerofill 屬性修改        例:int(5)    插入一個數'123',補填後為'00123'
  • 面試問爛的 MySQL 查詢優化,看完屌打面試官!
    show variables like'innodb_file_per_table如果innodbfileper_table 為 ON 將建立獨立的表空間,文件為tablename.ibd;如果innodbfileper_table 為 OFF 將數據存儲到系統的共享表空間,文件為ibdataX(X為從1開始的整數);.frm :是伺服器層面產生的文件
  • SmartDb 1.0.0 發布,支持多資料庫、多數據源、讀寫分離的極速...
    特性如下: 支持ORM操作、常見增刪改查、批量、分頁等功能 支持MySQL、Oracle、Postgresql、SqlServer 支持在mybatis、hibernate等項目上引入SmartDb 支持多數據源 支持分寫分離 支持枚舉Enum
  • mysqldump中的幾個坑
    記錄一下在mysqldump使用中遇到的幾個坑。
  • 資料庫基礎:mysql主從集群搭建
    本文轉載自【微信公眾號:java架構師進階之路,ID:gh_a39b0d322dde】經微信公眾號授權轉載,如需轉載與原文作者聯繫前言:Mysql資料庫沒有增量備份的機制還好mysql資料庫提供了一種主從備份的機制,其實就是把主資料庫的所有的數據同時寫到備份的資料庫中。實現mysql資料庫的熱備份。 要想實現雙機的熱備,首先要了解主從資料庫伺服器的版本的需求。要實現熱備mysql的版本都高於3.2。還有一個基本的原則就是作為從資料庫的數據版本可以高於主伺服器資料庫的版本,但是不可以低於主伺服器的資料庫版本。
  • 主庫n -> 從庫s - MySQL5.7多主一從(多源複製)同步配置 - 計算機...
    部署環境註:使用docker部署mysql實例,方便快速搭建演示環境。但本文重點是講解主從配置,因此簡略描述docker環境構建mysql容器實例。資料庫:MySQL 5.7.x (相比5.5,5.6而言,5.7同步性能更好,支持多源複製,可實現多主一從,主從庫版本應保證一致)作業系統:CentOS 7.x容器:Docker 17.09.0-ce鏡像:mysql:5.7主庫300:IP=192.168.10.212; PORT=4300; server-id=300; database=test3; table=user主庫400