值得收藏的 MySQL 超全知識點總結

文章目錄


1、MySQL 的相關概念介紹

注意,MySQL 的操作都是無法撤銷的,所以每一步都要小心,特別是更新,修改數據(除非用 事務,或者 要多備份)

注意,當我們用 SELECT 去查詢的時候,是以對象數據的鍵,去查詢的,因爲有 鍵,那麼查詢比較快(B+ 樹),所以需要說,用鍵去索引。也因此,鍵是要唯一的

MySQL 爲關係型數據庫(Relational Database Management System), 這種所謂的"關係型"可以理解爲"表格"的概念,一個關係型數據庫由一個或數個表格組成

其實也就是,一個 MySQL 數據庫(文件)類似於 excel 文件,而一個庫裏面,可以有多個表。而每個表裏面,有字段(對應的屬性),然後表中的每一行,存的就是數據信息。

  • 數據存放到表中,表再放到庫中
  • 一個庫可以由多張表,每張表具有唯一的表名用來標識自己
  • 表中有一個或多個列,列又稱爲“字段”,也就是第一行,表示了每一列存的數據的意義(比如 學號,姓名等等)
  • 表中每一行數據,相當於 C++ 中“對象”,也就是具體到 每一個事物的具體數據。

下圖是一個,表 的例子:

在這裏插入圖片描述

  • 表頭(header),也就是 字段;表示這一列的意義(同時也會限制了對應的數據類型,比如 姓名那一列的就是字符串)
  • 列(row):具有相同數據類型的數據的集合;
  • 行(col):每一行用來描述某個人/物的具體信息(相當於是具體到 對象上,比如圖中的每一行就是每一個學生的信息)
  • 鍵(key):表中用來識別某個特定的人\物的方法, 鍵的值在當前列中具有唯一性。(其實相當於是對具體對象人的標識符,因此要唯一性,比如圖中,id 可以認爲是學號,每個學號是獨立的,所以可以作爲鍵。但是名字就不能,萬一出現重名的)。選擇鍵,一定要是唯一的,而且那一列不能非空,這樣子纔有唯一標識性
  • 值(value): 行的具體信息, 每個值必須與該列(字段指定的)的數據類型相同;

只要設定的鍵不同,其他數據即使一樣,也是認爲是不同的數據


2、MySQL 的基本組成

和Linux 的shell 腳本一樣。我們一般在 shell 上使用指令,都是一條一條的。在 MySQL 的時候,指令也是一條一條的。

但是我們可以通過寫腳本(指令的結合體,類似寫 cpp 一樣),寫成一個可以批處理的文件,這樣子執行腳本,就會執行裏面的指令。
同樣的,也可以在控制檯上,一條一條的執行指令,不用到腳本。

2.0、註釋

單行註釋:# 註釋文字
多行註釋:/* 註釋文字 */

2.1、標識符

類似 CPP,標識符就是給變量,表,庫起名,一般都是用:標識符由字母、數字或下劃線(_)組成,且第一個字符必須是字母或下劃線。

2.2、區分大小寫(不同操作系統不一樣)

對於 Windows 而言,不區分大小寫,比如 SELECT 就相當於是 select

對於 Linux,就是會區分大小寫

  • 數據庫名與表名是嚴格區分大小寫的;
  • 表的別名是嚴格區分大小寫的;
  • 列名與列的別名在所有的情況下均是忽略大小寫的;
  • 變量名也是嚴格區分大小寫的;

一般來說,習慣性給 關鍵字,函數之類的大寫,然後其他的一般小寫,比如別名,庫名,表名之類的。

2.3、關鍵字

MySQL 的關鍵字衆多,這裏不一一列出,在學習中學習。這些關鍵字有自己特定的含義,儘量避免作爲標識符。

2.4、語句(指令)

MySQL 語句是組成 MySQL 腳本的基本單位,每條語句能完成特定的操作,他是由 SQL 標準語句 + MySQL 擴展語句組成

每一行的語句結束,都加上 ;,表示這一行指令輸入結束。不加 ;,會提示讓你繼續輸入。

每條命令根據需要,可以進行縮進,或者換行(建議關鍵字放一行,要要查詢的放一行)。

2.5、函數

對於MySQL,也有一些函數可以使用的(比如像 SUM,AVG,求某一列(字段)的最大值,平均值)

MySQL 函數用來實現數據庫操作的一些高級功能, 這些函數大致分爲以下幾類:字符串函數、數學函數、日期時間函數、搜索函數、加密函數、信息函數。


3、MySQL 中的數據類型

這個在另一個文章裏面介紹了:MySQL 數據庫的數據類型

4、操作 數據庫

4.1、啓動/關閉 MySQL 服務

windows的,命令行下運行:(cmd 或者 powershell)

啓動服務net start mysql
關閉服務net stop mysql
卸載sc delete mysql

Linux

查看 MySQL 服務

方法一:ps -ef | grep mysql
方法二:netstat -nlp

啓動MySQL 服務

命令行方式:

cd /usr/bin
./mysqld_safe &

服務方式:

service mysql start

// 如果服務已經啓動中,可以用下面指令使其 重啓服務
service mysql restart

關閉 MySQL 服務

命令行方式:mysqladmin -u root shutdown

服務方式:service mysql stop

4.2、登陸到 MySQL

當 MySQL 服務已經運行的時候,我們就可以通過 cmd、shell(甚至CPP代碼)來登陸到 數據庫中。

同樣的,登陸的時候,需要 用戶名 和 密碼,其登陸指令爲:

mysql -h 主機號 -u 用戶名 -p

# -h 後面,
  • -h:用於指定客戶端所要登錄的MySQL主機名(也就是,mysql服務是運行在哪個 IP 地址的主機上的),如果是 當前機器上的MySQL服務,該參數可以省略
  • -u:所要登陸的用戶名(root用戶,或者其他創建的MySQL服務中的用戶)
  • -p:告訴服務器將會使用一個密碼來登錄

當回車之後,會得到要輸入密碼的響應,此時輸入密碼即可。

然後命令提示符會一直以 mysql> 加一個閃爍的光標等待命令的輸入, 輸入 exit 或 quit 退出登錄。(表明我們此時已經登陸到了,MySQL 數據庫中了)

例子

mysql -u root -p
# 這個是,因爲沒有 -h,所以相當於是,登陸到本機上的 MySQL 數據庫中

mysql -h 192.168.2.1 -u root -p
# 這個是登陸到,192.168.2.1 這個IP 對應的機器上的,MySQL 數據庫中

4.3、修改登陸密碼

有幾種方法:

方法一:藉助 MySQL 第三方圖形化界面軟件 來修改

  1. 先登陸到對應數據庫中
  2. 點擊上方的用戶
  3. 選擇要更改的用戶名,點擊上方的編輯用戶
  4. 然後輸入新密碼,點擊保存即可。

方法二:用 SET PASSWORD 命令

首先先登陸到 MySQL 中。

格式:mysql> set password for 用戶名@localhost = password('新密碼');

例子:mysql> set password for root@localhost = password('123');

方法三:用 mysqladmin

不用先 登陸到 MySQL

格式:mysqladmin -u用戶名 -p舊密碼 password 新密碼

例子:mysqladmin -uroot -p123456 password 123

方法四:用UPDATE直接編輯user表

我們發現,其實 MySQL 的登錄用戶的信息,也是保存在一個 數據庫的表中,是保存在 mysql 庫 的 user 表中。

因此,我們直接對其 user 表進程修改。

要先登陸到 MySQL

mysql> use mysql;  
mysql> update user set password=password('123') where user='root' and host='localhost';  
mysql> flush privileges; 

先進入到 對應的 mysql庫,然後直接更新 user 表。最後要多那一句,這樣子用戶的更改密碼後纔有效(否則要手動重啓 MySQL 服務器)

方法五:忘記 root 密碼時,可以這樣

以 Windows 爲例(上面的四種方法,都是可以在 Linux 或者 Windows 上使用)

目前的這個,是以 Windows 爲例的,具體 Linux 可不可以用,還沒試過。

  1. 關閉正在運行的MySQL服務。
  2. 打開DOS窗口,轉到mysql\bin目錄。
  3. 輸入mysqld --skip-grant-tables 回車。--skip-grant-tables 的意思是啓動MySQL服務的時候跳過權限表認證。
  4. 再開一個DOS窗口(因爲剛纔那個DOS窗口已經不能動了),轉到mysql\bin目錄。
  5. 輸入mysql回車,如果成功,將出現MySQL提示符 >。
  6. 連接權限數據庫: use mysql;
  7. 改密碼:update user set password=password("123") where user="root";(別忘了最後加分號) 。
  8. 刷新權限(必須步驟):flush privileges; 。
  9. 退出 quit
  10. 註銷系統,再進入,使用用戶名root和剛纔設置的新密碼123登錄

4.4、MySQL 用戶設置

在MySQL 中,記錄登陸的賬戶密碼,其實也是用一個 mysql 庫中的 user 表 來記錄的(同樣可以用 SELECT 查詢用戶信息,INSERT INTO 增加新用戶,DELETE 刪除用戶)

類似於 Linux,MySQL 也是一開始有一個超級榕湖 root,其可以創建其他用戶(這樣子,其他用戶有權限設置,同時也可以訪問該數據庫)

需要添加 MySQL 用戶,你只需要在 mysql 數據庫中的 user 表添加新用戶即可

例子(以 Linux的)

以下爲添加用戶的的實例,用戶名爲 guest,密碼爲 guest123,並授權用戶可進行 SELECT, INSERT 和 UPDATE操作權限(創建用戶,並授權):

root@host# mysql -u root -p
Enter password:*******
mysql> use mysql;
Database changed

# 增加新用戶
mysql> INSERT INTO user 
          (host, user, password, 
           select_priv, insert_priv, update_priv) 
           VALUES ('localhost', 'guest', 
           PASSWORD('guest123'), 'Y', 'Y', 'Y');
Query OK, 1 row affected (0.20 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 1 row affected (0.01 sec)

mysql> SELECT host, user, password FROM user WHERE user = 'guest';
+-----------+---------+------------------+
| host      | user    | password         |
+-----------+---------+------------------+
| localhost | guest | 6f8c114b58f2ce9e |
+-----------+---------+------------------+
1 row in set (0.00 sec)
  • 在添加用戶時,請注意使用MySQL提供的 PASSWORD() 函數來對密碼進行加密(如果這個函數沒有了,可以用 MD5()來加密)。 你可以在以上實例看到用戶密碼加密後爲: 6f8c114b58f2ce9e.
  • 在注意需要執行 FLUSH PRIVILEGES 語句。 這個命令執行後會重新載入授權表。如果你不使用該命令,你就無法使用新創建的用戶來連接 mysql 服務器,除非你 重啓mysql服務器。
  • 你可以在創建用戶時,爲用戶指定權限,在對應的權限列中,在插入語句中設置爲 ‘Y’ 即可,用戶權限列表如下:
    • select_priv
    • insert_priv
    • update_priv
    • delete_priv
    • create_priv
    • drop_priv
    • reload_priv
    • shutdown_priv
    • process_priv
    • file_priv
    • grant_priv
    • references_priv
    • index_priv
    • alter_priv

4.5、創建一個數據庫:CREATE

使用 create database 語句可完成對數據庫的創建, 創建命令的格式如下

CREATE DATABASE [IF NOT EXISTS] 數據庫名 [其他選項];

# [] 表示這個參數,可以有,也可以沒有
# IF NOT EXISTS 表示,如果創建的數據庫已經存在,就不用再創建。如果不存在,就創建
# 關鍵字,我們一般用大寫
# 其他選項是可選的,可以有,也可以沒有。其選項一般用於設置創建的這個數據庫的一些屬性
# 語句最後,要加上 ; 分號,表示這一行指令輸入結束

比如說,我們需要創建一個名爲 testdb 的數據庫, 在命令行下執行以下命令:

CREATE DATABASE IF NOT EXISTS testdb CHARACTER SET utf8;

# 這個是,創建了一個 testdb 的數據庫,同時指定了 編碼爲 utf8 編碼(也可以是 gbk 編碼)
# 指定數據庫編碼,就是 一個可選選項
# 其中,我們關鍵字都是大寫

創建成功時會得到 Query OK, 1 row affected(0.02 sec) 的響應

注意MySQL語句以分號(;)作爲語句的結束,若在語句結尾不添加分號時,命令提示符會以 -> 提示你繼續輸入(有個別特例, 但加分號是一定不會錯的)

4.6、選擇所要操作的數據庫:USE

我們要操作數據庫裏面的信息時,必須先選擇(進入)到這個數據庫文件中

上面創建數據庫,類似創建一個 excel 文件,然後我們需要對 excel 文件操作,那就要打開。那麼我們也就是要打開 – 選擇 數據庫,才能對數據庫繼續操作

我們在登陸到 MySQL 後,可以用命令來選擇指定數據庫

USE 數據庫名;

比如我們進入上面創建的數據庫

USE testdb;

選擇成功後會提示: Database changed

如果是已經在一個數據庫中,想要切換另一個數據庫,也是直接用 USE 即可切換到 另一個指定的數據庫

4.7、刪除一個數據庫:DROP

刪除數據庫意味着數據庫中的所有數據和關聯對象將被永久刪除,並且無法撤消

相當於刪除了,整個 excel 文件

要刪除數據庫,請使用DROP DATABASE語句,如下所示

DROP DATABASE [IF EXISTS] 數據庫名;

# [] 表示這個選項參數,可以選擇使用,也可以不使用
# IF EXISTS 表示,檢查這個東西,在不在,只有在了,我們才進行刪除對應的數據庫。

例子,還是刪除我們上面那個創建的數據庫 testdb,即:

DROP DATABASE IF EXISTS testdb;

4.8、查看已經創建的所有數據庫:SHOW

SHOW DATABASES語句顯示 MySQL 數據庫服務器中的所有數據庫。

您可以使用SHOW DATABASES語句來查看您要創建的數據庫,或者在創建新數據庫之前查看數據庫服務器上的所有數據庫(也可以是是在選擇進入數據庫,或者刪除數據庫的時候,可以先查看,然後再進入/刪除 對應的數據庫)

例子

mysql> show databases;    # 查看所有數據庫

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| mytestdb           |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

4.9、取別名:AS或空格

我們知道,有的時候,數據庫名,或者後面的 表的字段,或者我們要操作 的東西很長,那麼此時我們就可以給他們 起別名

  • 便於理解
  • 如果要查詢的字段有重名的情況,使用別名可以區分開來

方法一:使用 AS

SELECT 100%98 AS 結果;
SELECT last_name AS, first_name ASFROM employees;

# 這樣子,我們後面就可以利用 別名 來進行操作。

方法二:直接空格代替 AS(相當於直接省略了 AS)

SELECT last_name 姓, first_name 名 FROM employees;

#案例:查詢salary,顯示結果爲output
SELECT salary AS 'output' FROM employees;

5、操作 表

5.1、創建數據庫表:CREATE TABLE

使用 CREATE TABLE (create table) 語句可完成對錶的創建, CREATE TABLE 的常見形式:

CREATE TABLE [IF NOT EXISTS] 表名稱(
        表頭列聲明
) engine=table_type;

首先,指定要在 CREATE TABLE 子句之後創建的表的名稱。表名在數據庫中必須是唯一的。IF NOT EXISTS是語句的可選部分,允許您檢查正在創建的表是否已存在於數據庫中。如果要創建的表已經存在,MySQL將忽略整個語句,不會創建任何新的表。強烈建議在每個 CREATE TABLE 語句中使用 IF NOT EXISTS 來防止創建已存在的新表而產生錯誤。

其次,括號中指定表的列表。字段的列用逗號(,)分隔。

最後,需要爲engine子句中的表指定存儲引擎。一般用默認值,就是不寫明即可,默認是 InnoDB

關於 表頭列表聲明,在表頭列聲明,比如有 學號,姓名,性別等字段聲明,每個字段聲明,一般由如下組成(然後多個字段,就是組合,每個字段之間,用 , 隔開即可)

column_name data_type[size] [UNSIGNED] [NOT NULL|NULL] [DEFAULT value] [AUTO_INCREMENT] [PRIMARY KEY]

# [] 都是可選項
# 最重要就是,一開始的,字段的名,對應設置的數據類型(有一些數據類型有限制 size 的),然後後面都是可選項
# 後面的都是設置,這個 字段的屬性

字段屬性可以設爲

字段屬性 含義
NULL 數據列(字段)可包含 NULL 值
NOT NULL 數據列(字段)不允許包含 NULL 值
DEFAULT 默認值,也就是這個字段後面對象的值,無說明就是設爲默認值
PRIMARY KEY 主鍵,只能有一個
AUTO_INCREMENT 自動遞增,適用於整數類型。指示每當將新行插入到表中時,列的值會自動增加。每個表都有一個且只有一個
UNSIGNED 無符號

例子

CREATE TABLE IF NOT EXISTS students
(
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name CHAR(8) NOT NULL,
    sex CHAR(4) NOT NULL,
    age TINYINT UNSIGNED NOT NULL,
    tel CHAR(13) NULL default '-'
);

例子解釋

CREATE TABLE IF NOT EXISTS tablename(columns) 爲創建數據庫表的命令,列(字段)的名稱以及該列(字段)的數據類型將在括號內完成;

括號內聲明瞭5列內容,id、name、sex、age、tel爲每列的名稱,,後面跟的是數據類型描述,列與列的描述之間用逗號(,)隔開;

id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY行進行介紹:

  • “id” 爲列的名稱;
  • “INT” 指定該列的類型爲 int(取值範圍爲 -8388608到8388607), 在後面我們又用 “UNSIGNED” 加以修飾, 表示該類型爲無符號型, 此時該列的取值範圍爲 0到16777215;
  • “NOT NULL” 說明該列的值不能爲空, 必須要填, 如果不指定該屬性, 默認可爲空;
  • “AUTO_INCREMENT” 需在整數列中使用, 其作用是在插入數據時若該列爲 NULL, MySQL將自動產生一個比現存值更大的唯一標識符值。在每張表中僅能有一個這樣的值且所在列必須爲索引列。
  • “primary key” 表示該列是表的主鍵, 本列的值必須唯一(鍵是唯一性,這列的值,不能出現重複), MySQL將自動索引該列(也就是,我們查找數據,雖然是找其他字段的值,但是都是根據 鍵 來索引查找的)。
  • 下面的 char(8) 表示存儲的字符長度爲8, tinyint的取值範圍爲 -127到128, default 屬性指定當該列值爲空時的默認值。

這些數據類型和對應屬性都在另一篇文章中說了:MySQL 的數據類型

有時候,很長的命令,直接輸入在 命令行的時候,容易出錯。所以可以通過用 腳本的方式,具體看後面 腳本的介紹

5.2、向表中插入數據:INSERT INTO

INSERT INTO 語句可以用來將一行或多行數據插到數據庫表中, 使用的一般形式如下:

INSERT INTO 表名 [(列名1, 列名2, 列名3, ...)] VALUES (1,2,3, ...);

也就是,我們給 表名 的那個表增加數據

  • 其中,如果 [] 是可選參數,當沒有寫明是 列(字段)名時,默認是給所有 列 都增加了數據(即 VALUES 中的數據是對應所有列的)
  • 如果註明了 列名,那麼此時,我們可以選擇,只給這些對應的列增加數據(那麼剩下的這行數據中的其他列,就是 NULL 或者 用該列的默認值)

例子

INSERT INTO students VALUES(NULL, "王剛", "男", 20, "13811371377");
# 忽略了 [] 列名,也就是 所有列都添加數據
# 還是一開始學生的那個表,依次是 id,name,sex,age,tel。
# id 雖然設置了NULL,但是 id 是AUTO_INCREMENT,所以會自動有一個值


INSERT INTO students (name, sex, age) VALUES("孫麗華", "女", 21);
# 這裏限定了 列明,也就是我們只添加部分數據。
# 對於 id,tel 沒有添加。而 id 是會自動賦值,tel 有默認值

5.3、更新表中的數據:UPDATE

UPDATE 語句可用來修改表中的數據, 基本的使用形式爲:

UPDATE 表名
SET 
    column_name1 = expr1,
    column_name2 = expr2,
    (列名稱 = 新值)
WHERE
    更新條件;

請注意,WHERE 子句非常重要,所以不應該忘記指定更新的條件。有時,您可能只想改變一行;但是,可能會忘記寫上 WHERE 子句,導致意外更新表中的所有行。

例子

UPDATE students 
SET 
    tel = default 
WHERE 
    id=5;
# 將 id = 5 的那些數據的 tel 設置爲 其默認值

UPDATE students 
SET 
    age = age + 1;
# 將所有數據(無 WHERE 限制)的 age 都增加 1

UPDATE students 
SET 
    name = '張偉鵬', 
    age = 19 
WHERE 
    tel = '13288097888' ;
# 將 手機號爲要求的那些數據,更改名字 和 年齡

5.4、刪除表中數據

5.4.1、刪除表中數據,不刪除表:delete

DELETE 語句用於刪除表中的數據, 基本用法爲

DELETE FROM 表名稱 
WHERE 刪除條件;

如果沒有限制條件 WHERE,那就是刪除整個表中的所有數據(只是刪除數據,而原來的表頭,字段,表還是在的)

如果有限制條件,那就是刪除滿足限制條件的那些數據

其中,還可以和 ORDER BY(排序)和 LIMIT(限制刪除前幾條數據)結合在一起。

例子

DELETE FROM customers
ORDER BY customerName
LIMIT 10;
# 客戶名稱按字母排序客戶,並刪除前 10 個客戶

DELETE FROM customers
WHERE country = 'France'
ORDER BY creditLimit
LIMIT 5;
# 選擇法國(France)的客戶,按升序按信用額度(creditLimit)進行排序,並刪除前5個客戶

還可以是多表的刪除,和 後邊的 連接一起結合使用

5.4.2、刪除表中數據,不刪除表:truncate

TRUNCATE TABLE 表名;

刪除 表名 對應的這個 表中的數據。(只是刪除數據,而原來的表頭,字段,表還是在

5.4.3、刪除表中數據,刪除整個表:drop

DROP TABLE 表名;

注意,這個是,刪除整個表,也就是說,除了刪除了數據內容,還會將這個 表 直接銷燬,也就沒這個表了。

5.4.4、delete、truncate、drop 的區別(面試題

相同點

truncate 和不帶 where 子句的 delete,以及 drop 都會刪除表內的數據

不同點

  1. truncate 和 delete 只刪除數據不刪除表的結構(字段等都還在);drop 語句將刪除表的結構(也就是整個 表 都沒了,字段也沒了)
  2. delete 語句是數據庫操作語言(dml),這操作會放到rollback segement 中,事務提交之後才生效;如果有相應的 trigger,執行的時候將被觸發。truncate、drop 是數據庫定義語言(ddl)操作立即生效,原數據不放到 rollback segment 中,不能回滾,操作不觸發 trigger。
  3. delete 語句不影響表所佔用的 extent,高水線(high watermark)保持原位置不動
    顯然 drop 語句將表所佔用的空間全部釋放。
    truncate 語句缺省情況下見空間釋放到 minextents個 extent,除非使用reuse storage;truncate 會將高水線復位(回到最開始)。
  4. 速度,一般來說: drop> truncate > delete
  5. 安全性:小心使用 drop 和 truncate,尤其沒有備份的時候.否則哭都來不及

5.4.5、delete、truncate 的區別(面試題

前面說了,delete 和 truncate 都是隻刪除數據,不刪除表的結構,但他們之間還是有小區分的。

  1. delete可以加where條件,truncate不可以。
  2. truncate刪除,效率高一些。DELETE 語句每次刪除一行,並在事務日誌中爲所刪除的每行記錄一項。TRUNCATE TABLE 通過釋放存儲表數據所用的數據頁來刪除數據,並且只在事務日誌中記錄頁的釋放。
  3. 假如要刪除的表中有自增長列,如果用delete刪除後,再插入數據,自增長列的值從斷點開始。而truncate刪除後,再插入數據,自增長列的值從1開始。
  4. truncate刪除沒有返回值,delete刪除有返回值。
  5. truncate刪除不能回滾,delete刪除可以回滾。

5.5、查詢該數據庫中所有的表:SHOW TABLES

在已經進入某個數據庫中,想看這個庫裏面有哪些表格,就可以用下面的命令:

SHOW TABLES;

6、從表中查詢數據

去重

SELECT DISTINCT department_id FROM employees;
# 查詢員工表涉及到的所有部門編號(不重複的顯示)

DISTINCT 關鍵字 可以讓顯示的結果,去重。

6.1、基本查詢表中的數據指令:SELECT

當我們數據庫中有數據了,我們需要查詢,獲取數據時,可以用 SELECT 語句,其基本用法爲:

SELECT 
    column_1, column_2, ...
FROM
    table_1
[查詢條件];
# 需要從 table_1 中,獲取到 列名爲 column_1, column_2, ... 的數據(並顯示出來)
# 如果有 額外的查詢條件,就要滿足,這個後面會繼續分析

如果要查詢 表中的所有內容(所有列),就使用 通配符 * 來SELECT * FROM tablename

舉個例子

要查詢 students 表中所有學生的名字和年齡,那麼就是 SELECT name, age FROM students;,其執行結果如下:

mysql> select name, age from students;
+--------+-----+
| name   | age |
+--------+-----+
| 王剛   |  20 |
| 孫麗華 |  21 |
| 王永恆 |  23 |
| 鄭俊傑 |  19 |
| 陳芳   |  22 |
| 張偉朋 |  21 |
+--------+-----+
6 rows in set (0.00 sec)

注意了,我們 不僅可以查詢到 對應的字段,我們還可以對字段進行處理後,再顯示(這裏還可以結合 別名

mysql> select name, age * 10 十倍年紀 from stu;
+------+----------+
| name | 十倍年紀 |
+------+----------+
||      200 |
||      200 |
||      200 |
||      180 |
+------+----------+
4 rows in set (0.00 sec)

# 我們將 age * 10 再顯示出來,但是我們顯示的時候,給其取了別名,那麼顯示出來的時候,就是用別名顯示。
# 十倍年紀,相當於是一個 標識符,而不是字符串,所以是直接寫。

關於 [查詢條件]

實際上,我們的查詢條件,可以有很多種類型,不單單是 WHERE,還可以用其他的,甚至 MySQL 的函數也可以,大概爲下面那些:

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    conditions
GROUP BY column_1
HAVING group_conditions
ORDER BY 排序列表 [asc / desc]
LIMIT offset, length;

語句中的SELECTFROM語句是必須的,其他部分是可選的。

  • SELECT之後是逗號分隔列或星號(*)的列表,表示要返回所有列。
  • FROM指定要查詢數據的表或視圖。
  • JOIN根據某些連接條件從其他表中獲取數據。(連接查詢)
  • WHERE過濾結果集中的行。(條件查詢
  • GROUP BY將一組行組合成小分組,並對每個小分組應用聚合函數。(分組查詢
  • HAVING過濾器基於GROUP BY子句定義的小分組。
  • ORDER BY指定用於排序的列的列表。(排序查詢
  • LIMIT限制返回行的數量。(分頁查詢

這些都在緊接着的小節來講解

6.2、通過條件篩選查詢:WHERE

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    conditions
GROUP BY column_1
HAVING group_conditions
ORDER BY 排序列表 [asc / desc]
LIMIT offset, length;

發現,在使用 SELECT 查詢的時候,我們可以用 WHERE 來限制,我們想查詢到的數據,滿足一定的條件(比如,是男的,是女的)

關於 WHERE 的時候,一般是(也不僅僅是 SELECT 纔可以用,前面講的 UPDATE 中 也可以結合 WHERE 使用):

SELECT
	查詢列表
FROM
	表名
WHERE
	篩選條件;

其總共分爲三類:

  • 按條件表達式篩選。包括:>, <, =, !=, <>, >=, <=,(!= 和 <>都可以表示不等於)
  • 按邏輯表達式篩選and, or, not 分別得意思就是,與,或,非。
  • 模糊查詢。會包括 LIKE, BETWEEN AND, IN, IS NULL, IS NOT NULL

6.2.1、按條件表達式篩選

包括:>, <, =, !=, <>, >=, <=,(!= 和 <>都可以表示不等於)

注意,這裏判斷 等於是 =,而不是 ==

#案例1:查詢 工資 > 12000 的員工信息
SELECT
	*
FROM
	employees
WHERE
	salary > 12000;

	
#案例2:查詢部門編號 不等於90號 的員工名和部門編號
SELECT
	last_name,
	department_id
FROM
	employees
WHERE
	department_id != 90;
# != 也可以換成 <>

6.2.2、按邏輯表達式篩選

and, or, not 分別的意思就是,與,或,非。

#案例1:查詢工資在10000到20000之間的員工名,工資和獎金
SELECT
	last_name,
	salary,
	commission_pct
FROM
	employees
WHERE
	salary >= 10000 AND salary <= 20000;
# 因爲是要找 一個範圍,所以用 AND,相當於是 && 連接

	
#案例2:查詢部門編號不在90-110之間,或者工資高於15000的員工信息
SELECT
	*
FROM
	employees
WHERE
	department_id < 90 OR department_id > 110 OR salary > 15000;
# 根據要求,應該是 小於 90,或者大於 110;或者大於 150
# OR 相當於是 || 

6.2.3、模糊查詢(結合在 WHERE 中使用的)

包括 LIKE, BETWEEN AND, IN, IS NULL, IS NOT NULL

6.2.3.1、LIKE:判斷是否模糊匹配字符串

/*
一般和通配符搭配使用。通配符:
	% 任意多個字符,包含0個
	_ 任意單個字符

*/
# 案例1:查詢員工名中包含 字符a 的員工信息
SELECT
	*
FROM
	employees
WHERE
	last_name LIKE '%a%';	
# 因爲我們是要查找名字中有 a,也就是 名字 中要有 a
# 那麼就是 %a%,無論前面後面有沒有其他字符(甚至無),只要出現 a 就可以


#案例2:查詢員工名中 第3個字符爲n,第五個字符爲l 的員工名和工資
SELECT
	last_name,
	salary
FROM
	employees
WHERE
	last_name LIKE '__n_l%';
# 那就是要求,判斷條件 WHERE 中,員工名 要是 __n_l% 的結構(因爲後面可以是任意多個字符,所以是 %)
	
	
#案例3:查詢員工名中 第二個字符爲_ 的員工名(轉義字符)	
SELECT
	last_name
FROM 
	employees
WHERE 	 
	last_name LIKE '_\_%';	
# 因爲 _ 是特殊字符,那麼要判斷 _ 就需要是 \_,轉義字符
# 那麼就是 _\_% 即可,第二個是 字符是 _

6.2.3.2、BETWEEN AND:判斷是否在一個區間

/*
BETWEEN a AND b,其實就是 [a, b],包含邊界值
兩個臨界值順序不能調換

*/

#案例1:查詢員工編號在100到120之間的員工信息
SELECT
	*
FROM
	employees
WHERE
	employee_id BETWEEN 100 AND 120;
	
# 相當於是
SELECT
	*
FROM
	employees
WHERE
	employee_id >= 100 AND employee_id <= 120;

6.2.3.3、IN:判斷是不是列表中的某一項

/*
含義:用於判斷某字段的值是否屬於in列表中的某一項
特點:
	①使用in提高語句簡潔度
	②in列表的值類型必須統一或者兼容
	③不支持通配符
*/

#案例:查詢員工的工種編號是 IT_PROT, AD_VP, AD_PRES中 的一個的員工名和工種編號
SELECT
	last_name,
	job_id
FROM
	employees
WHERE
	job_id IN ('IT_PROT' ,'AD_VP' , 'AD_VP');

# 相當於----------------------------------------------------
SELECT
	last_name,
	job_id
FROM
	employees
WHERE
	job_id='IT_PROT' OR job_id='AD_VP' OR job_id='AD_VP';

6.2.3.4、IS NULL:判斷值是不是NULL

因爲判斷 是不是 NULL 值,無法用 =, !=, <> 來判斷,所以,只能用 IS NULLIS NOT NULL 來判斷,對應的,是不是 NULL 值。

#案例1:查詢沒有獎金的員工名和獎金率
SELECT
	last_name,
	commission_pct
FROM
	employees
WHERE
	commission_pct IS NULL;

6.3、排序查詢(返回結果按要求排序顯示):ORDER BY

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    篩選條件
GROUP BY column_1
HAVING group_conditions
ORDER BY 排序列表 [asc / desc]
LIMIT offset, length;

這裏面,有一個 ORDER BY,就是說,我們獲取到的數據,顯示的時候,可以按照我們要求以 column_1 來排序(升序、降序)來顯示

語法如下:

SELECT 
    column_1, column_2, ...
FROM
    table_1
WHERE
    篩選條件
ORDER BY 排序列表 [asc / desc]

# 1、asc代表升序,desc代表降序,默認不寫是升序
# 2、order by子句中可以支持單個字段、多個字段、表達式、函數、別名
# 3、order by 子句一般是放在查詢語句的最後面,但在limit子句 之前

例子

# 案例1:查詢員工信息,要求工資從高到低排序
SELECT * 
FROM employees 
ORDER BY salary DESC;
# 以 salary 從高到低的顯示。從高到低就是 降序。


#案例2:查詢部門編號 >=90 的員工信息,按入職時間的先後進行排序
SELECT *
FROM employees
WHERE department_id >= 90
ORDER BY hiredate ASC;


#案例3:按年薪高低顯示員工的信息和年薪
SELECT *, salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM employees
ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;
# 這裏除了原本的所有字段 * 顯示,還顯示多一列 年薪(起別名的)。也是安裝這個來排序
# 其實後面 ORDER BY salary*12*(1+IFNULL(commission_pct,0)) 可以寫成
# ORDER BY 年薪, 相當於下面這個:
SELECT *, salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM employees
ORDER BY 年薪 DESC;


#案例4:按姓名的長度顯示員工的姓名和工資 [按函數排序]
SELECT LENGTH(last_name) AS 字節長度, last_name,salary
FROM employees
ORDER BY 字節長度 DESC;
# 利用函數,計算 姓名的長度,從而可以排序


#案例6:查詢員工信息,要求先按工資升序,再按員工編號降序 [按多個字段排序]
SELECT * 
FROM employees
ORDER BY salary ASC, employee_id DESC;
# 整體按工資排序,工資相同時,按員工編號降序
# 排序的要求,可以是多個結合,按照前後優先級判斷。

6.4、連接查詢(多個表中讀取數據):JOIN

我們之前,都是在一張表中,讀取(查看)數據。那麼如果我們想要在多個 表中 查詢數據,就可以用到 JOIN 來實現,語法大致如下:

在 SELECT, UPDATE 和 DELETE 語句中使用 Mysql 的 JOIN 來聯合多表查詢。

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT | RIGHT] JOIN table_2 ON conditions
WHERE
    conditions

從中可以發現,JOIN 有三類:

  • INNER JOIN(內連接,或等值連接):獲取兩個表中字段匹配關係(相交信息)的記錄。
  • LEFT JOIN(左連接):獲取左表所有記錄,即使右表沒有對應匹配的記錄
  • RIGHT JOIN(右連接): 與 LEFT JOIN 相反,用於獲取右表所有記錄,即使左表沒有對應匹配的記錄

用實例來講解,會清楚。假設有兩個表:

mysql> use RUNOOB;
Database changed
mysql> SELECT * FROM tcount_tbl;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| 菜鳥教程  | 10           |
| RUNOOB.COM    | 20           |
| Google        | 22           |
+---------------+--------------+
3 rows in set (0.01 sec)
 
mysql> SELECT * from runoob_tbl;
+-----------+---------------+---------------+-----------------+
| runoob_id | runoob_title  | runoob_author | submission_date |
+-----------+---------------+---------------+-----------------+
| 1         | 學習 PHP    | 菜鳥教程  | 2017-04-12      |
| 2         | 學習 MySQL  | 菜鳥教程  | 2017-04-12      |
| 3         | 學習 Java   | RUNOOB.COM    | 2015-05-01      |
| 4         | 學習 Python | RUNOOB.COM    | 2016-03-06      |
| 5         | 學習 C      | FK            | 2017-04-05      |
+-----------+---------------+---------------+-----------------+
5 rows in set (0.01 sec)

6.4.1、INNER JOIN(內連接,或等值連接)

image

讀取的,要求兩個表中都存在的數據,假如 一個有,另一個沒有,那就不能讀取。

現在,我們想要讀取 runoob_tbl 表中所有 runoob_author 字段在 tcount_tbl 表對應的 runoob_count 字段值

此時就出現了兩個表同時讀取,其中是按照 runoob_author 來連接兩個表的

SELECT a.runoob_id, a.runoob_author, b.runoob_count 
FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鳥教程    | 10             |
| 2           | 菜鳥教程    | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
+-------------+-----------------+----------------+
4 rows in set (0.00 sec)

# 注意了,我們給連個 表起了別名,a 和 b。此時我們連接 a 和 b,以 ON 後面爲準(兩個表中的,runoob_author 相等)
# 顯示出來的內容,以 SELECT 爲準
# 現在就是,我們獲取兩個表中,有着相同內容 runoob_author,此時是相交連接,所以取出來的是,兩者 共有的

6.4.2、LEFT JOIN(左連接)

image

讀取的,會讀取左邊數據表的全部數據,即便右邊表無對應數據。(LEFT,讀取全部左表的數據,如果對應的數據在右邊中無,那麼就設爲 NULL)

讀取左邊的數據表 runoob_tbl 的所有選取的字段數據,即便在右側表 tcount_tbl中 沒有對應的 runoob_author 字段值。

SELECT a.runoob_id, a.runoob_author, b.runoob_count 
FROM runoob_tbl a LEFT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鳥教程    | 10             |
| 2           | 菜鳥教程    | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
| 5           | FK              | NULL           |
+-------------+-----------------+----------------+
5 rows in set (0.01 sec)

# 此時,雖然還是以 runoob_author 爲準,但是我們優先讀 左邊 runoob_tbl,發現了 FK 在 右邊不存在,但是照樣還是顯示了。
# 而對應的 b.runoob_count 沒有 FK 的數據,所以設爲了 NULL

6.4.3、RIGHT JOIN(右連接)

類似 LEFT JOIN,只是反過來了而已。

image

會讀取右邊數據表的全部數據,即便左邊邊表無對應數據。

SELECT a.runoob_id, a.runoob_author, b.runoob_count 
FROM runoob_tbl a RIGHT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鳥教程    | 10             |
| 2           | 菜鳥教程    | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
| NULL        | NULL            | 22             |
+-------------+-----------------+----------------+
5 rows in set (0.01 sec)

# 此時,對 tcount_tbl 的全部數據讀取。
# 發現在 tcount_tbl 有一個 Google 在 runoob_tbl 沒有,但是還是顯示出來了,因爲要全部 tcount_tbl 的數據
# 只是,沒有的值,我們就用 NULL 顯示。

6.5、MySQL函數

舉例一些常用的,比較齊全的看:https://www.runoob.com/mysql/mysql-functions.html

對於函數,我們有時候使用,會比較方便,可以實現一些功能,方便。

字符函數:length  concat substr
instr trim upper lower
lpad rpad replace

數學函數: round ceil floor truncate mod

日期函數:now curdate curtime year month monthname 
day hour minute second str_to_date  date_format

其他函數:version database user

控制函數: if case

6.5.1、字符函數

#1. length 獲取參數值的字節個數
SELECT LENGTH('john');#4
SELECT LENGTH('張三丰hahaha');#15,utf8一個漢字佔3個字節


#2. concat 拼接字符串(用下劃線拼接)
SELECT CONCAT(last_name,'_',first_name) FROM employees;


#3. upper,lower
SELECT UPPER('john');#變大寫
SELECT LOWER('JOHN');#變小寫
#示例:將姓變大寫,名變小寫,拼接 
SELECT CONCAT(UPPER(last_name),LOWER(first_name)) AS 姓名 FROM employees;


#4. substr,substring
#注意索引從1開始,下語句輸出:和李四
#截取從指定索引處後面所有字符
SELECT SUBSTR('張三和李四',3) out_put;

#截取從指定索引處指定字符長度的字符
#下面語句輸出:張三
SELECT SUBSTR('張三和李四',1,2) out_put;

#案例:姓名中首字符大寫,其他字符小寫,用_拼接,顯示出來
SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2))) output
FROM employees;


#5. instr
#返回子串的起始索引,找不到返回0
SELECT INSTR('楊不悔愛上了殷六俠','殷六俠') AS out_put


#6、trim 去掉首尾的字符,默認是去除 空格。
#輸出張翠山
SELECT LENGTH(TRIM('    張翠山      ')) AS out_put;
#輸出張aaaa翠山
SELECT TRIM('a' FROM 'aaaa張aaaa翠山aaaaaaaa') AS out_put;


#7、 lpad  用指定的字符實現左填充指定長度
#輸出*******殷素素
SELECT LPAD('殷素素',10,'*') AS out_put;
#輸出:殷素
SELECT LPAD('殷素素',2,'*') AS out_put;


#8、 rpad  用指定的字符實現右填充指定長度
#輸出:殷素素ababababa
SELECT RPAD('殷素素',12,'ab') AS out_put;


#9、replace 替換
SELECT REPLACE('張無忌愛上了周芷若','周芷若','趙敏') AS out_put;

6.5.2、數學函數

#1、round四捨五入
SELECT ROUND(1.65);#2
SELECT ROUND(-1.45);#-1
SELECT ROUND(1.567,2);#1.57,小數點後保留2位


#2、ceil向上取整(返回>=該參數的最小整數)
SELECT CEIL(-1.02);#-1
SELECT CEIL(1.00);#1


#3、floor 向下取整,返回<=該參數的最大整數
SELECT FLOOR(-9.99);#-10


#4、truncate 截斷
SELECT TRUNCATE(1.65,1);#1.6;


#5、mod 取餘(也可以直接用 % 運算符)
/*
mod(a,b) : a-a/b*b

mod(-10,-3) : -10-(-10)/(-3)*(-3)=-1;
*/
SELECT MOD(10,-3);#1

6.5.3、日期函數

#1、now:返回當前系統日期加時間
SELECT NOW();


#2、curdate 返回當前系統日期,不包含時間
SELECT CURDATE();


#3、curtime() 返回當前時間,不包含日期
SELECT CURTIME();

#4、可以獲取指定的部分,年,月,日,小時,分,秒
SELECT YEAR(NOW()) AS;
SELECT YEAR('1998-1-1');

SELECT YEAR(hiredate)FROM employees;

SELECT MONTH(NOW());
SELECT MONTHNAME(NOW());#顯示英文月份

#5、str_to_date 將日期格式的字符轉換成指定格式的日期
# 將對應的字符串(要指明其形式),然後轉化爲 標準的 年月日的日期格式
/*
%Y 四位的年份
%y 2位的年份
%m 月份 (01,02,...12)
%c 月份(1,2,..., 12)
%d 日
%H 小時(24)%h(12)
%i 分鐘  %s秒
*/
SELECT STR_TO_DATE('9-13-1999','%m-%d-%Y') 日期;#1999-09-13
SELECT STR_TO_DATE ('2020-4-17','%Y-%c-%d') AS output;#2020-4-17

#查詢入職日期爲1992-4-3的員工信息
SELECT * FROM employees WHERE hiredate='1992-4-3';
SELECT * FROM employees WHERE hiredate=STR_TO_DATE('4-3 1992','%c-%d %Y');


#6、date_format 將日期轉換成字符
# 將 標準的日期格式,轉化爲 我們想要的 字符串格式,方便用於輸出顯示
SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS output;#20年4月17日

#查詢有獎金的員工名和入職日期(xx月/xx日 xx年)
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %Y年') 入職日期
FROM employees
WHERE commission_pct IS NOT NULL;

6.5.4、其他函數

SELECT VERSION();
SELECT DATABASE();#查看當前庫
SELECT USER();

6.5.5、流程控制函數

#1、IF 函數:if else 的效果

SELECT IF(10>5,'大','小');

SELECT last_name,commission_pct,IF(commission_pct IS NULL,'沒獎金','有獎金') 備註
FROM employees;


#2.case函數的使用一: switch case的效果
/*
case 要判斷的字段或表達式
when 常量1 then要顯示的值1或語句1;
when 常量2 then要顯示的值2或語句2;
...
else 要顯示的值n或語句n
end
(搭配select當表達式,then加一個值,或者不搭配select當語句)
*/
/*案例:查詢員工的工資:要求
部門號=30,顯示的工資爲1.1倍
部門號=40,顯示的工資爲1.2倍
部門號=50,顯示的工資爲1.3倍
其他部門顯示原工資
*/

SELECT salary,department_id,
CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE salary
END AS 新工資
FROM employees;


#3.case函數的使用二: 類似於多重if
/*
case  
when 條件1 then 要顯示的值1或語句1
when 條件2 then 要顯示的值2或語句2
...
else 要顯示的值n或語句n
end
*與上一種情況的不同就是case後不加表達式
*/

#案例:查詢員工的工資情況
/*
如果工資>20000,顯示A級別
如果工資>15000,顯示B級別
如果工資>10000,顯示C級別
否則顯示D級別
*/

SELECT salary,
CASE
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
WHEN salary>10000 THEN 'C'
ELSE 'D'
END AS 工資級別
FROM employees;

6.5.6、分組函數

#六、分組函數
/*
功能:用作統計使用,又稱爲聚合函數或統計函數或組函數
分類:sum 求和、avg平均值、max最大值、min最小值、count計算 非NULL 個數
特點
1、sum,avg用於處理數值型。max,min,count可以處於任何類型
2、以上分組函數都忽略null值
3、可以和distinct搭配實現去重
4、count函數的單獨介紹
5、和分組函數一同查詢的字段要求是group by後的字段
*/

#1.簡單的使用
SELECT SUM(salary) FROM employees;
SELECT SUM(salary) ,ROUND(AVG(salary),2)  FROM employees;
SELECT MAX(salary) ,MIN(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT COUNT(salary) FROM employees;

#2.參數支持哪些類型
 SELECT SUM(last_name),AVG(last_name) FROM employees;
 SELECT SUM(hiredate),AVG(hiredate) FROM employees;
 #無意義,不這樣用,SUM 和 AVG 只能算數值類型
 
 SELECT MAX(last_name),MIN(last_name) FROM employees;
 SELECT MAX(hiredate),MIN(hiredate) FROM employees;
 #支持
 
 SELECT COUNT(last_name) FROM employees; #計算非空的值 107
 SELECT COUNT(commission_pct) FROM employees;#35
 
 
 #3、是否忽略null
 SELECT SUM(commission_pct),AVG(commission_pct) FROM employees;
  
  
#4、和distinct搭配
SELECT SUM(DISTINCT salary), SUM(salary) FROM employees;
SELECT COUNT(DISTINCT salary), COUNT(salary) FROM employees;
  
  
#5、count函數的詳細介紹
SELECT COUNT(salary) FROM employees;
SELECT COUNT(*) FROM employees;#統計每一列的數目,即所有行數
SELECT COUNT(1) FROM employees;#和上一語句效果一樣
  
#6、和分組函數一同查詢的字段有限制
SELECT AVG(salary),employee_id FROM employees;#這個員工id查出來沒有意義  

6.6、分組查詢

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    conditions
GROUP BY column_1   # 這個就是 分組查詢
HAVING group_conditions
ORDER BY column_1
LIMIT offset, length;   # 這個就是 分頁查詢

GROUP BY 語句根據一個或多個列(如果是多個,就直接接在後面 , 隔開)對結果集進行分組。

在分組的列上我們可以使用 COUNT, SUM, AVG,等 分組函數

大概的 分組查詢的 語法:

SELECT column_name, function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;

# 按照 column_name 分組,然後顯示 column_name 和 其分組中記錄對應的 分組函數
# 其中 function 指的是 分組函數,SUM,MAX 之類的
# 要求,我們SELECT 後操作的列,也要出現在 GROUP BY 後
# group by子句支持單個字段分組,多個字段分組(多個字段之間用逗號隔開無順序要求)

舉個實例

/*
+----+--------+---------------------+--------+
| id | name   | date                | singin |
+----+--------+---------------------+--------+
|  1 | 小明 | 2016-04-22 15:25:33 |      1 |
|  2 | 小王 | 2016-04-20 15:25:47 |      3 |
|  3 | 小麗 | 2016-04-19 15:26:02 |      2 |
|  4 | 小王 | 2016-04-07 15:26:14 |      4 |
|  5 | 小明 | 2016-04-11 15:26:40 |      4 |
|  6 | 小明 | 2016-04-04 15:26:54 |      2 |
+----+--------+---------------------+--------+
*/
# 現在有以上的表格,我們現在,按照 名字進行分組,同時統計每個人有幾條記錄

SELECT name, COUNT(*) 
FROM employee_tbl 
GROUP BY name;   

# 按照 name 分組,一個人,對應很多記錄,分組後,只有 name 是不重複,然後統計了對應的記錄條數。
/* 顯示結果如下:
+--------+----------+
| name   | COUNT(*) |
+--------+----------+
| 小麗 |        1 |
| 小明 |        3 |
| 小王 |        2 |
+--------+----------+
3 rows in set (0.01 sec)
*/

6.7、分頁查詢(指明讀取數據的條數)

應用場景:當要顯示的數據一頁顯示不全時,那就要分頁顯示

比如說網頁顯示成績,一次可以顯示 10 門成績,總共有 25 門成績。那麼此時,一次性讀 10 門課成績,也顯示不完。因此第一頁的時候,我們就讀取前 10 條數據來顯示。當有人點擊下一頁的時候,再加載 後 10 條數據來顯示。
所以,這個 分頁查詢 指明瞭我們一次讀幾條數據,讀的是,哪幾條數據

基本格式

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    conditions
GROUP BY column_1
HAVING group_conditions
ORDER BY column_1
LIMIT offset, length;   # 這個就是 分頁查詢

分頁查詢,一般是放在最後面。有兩個參數

  • offset:這次讀取的數據,是從 offset 這個位置開始讀取(然後往後讀取 length 條)。這個下標是從 0 開始的。
    • 比如我們從 第 5 條數據開始讀取,那就是 offset = 5 - 1 = 4
  • length:要讀取的數據 條數,即我們這次要讀取 length 條數據

如果我們要讀取 第 a 到 第 b 條數據,其實要讀取的,就是:LIMIT a - 1 b - a + 1

如果 LIMIT 後面只跟一個參數,表示 省略了 offset,此時省略 offset 就是 默認 offset = 0

例子

#案例1:查詢前五條員工信息
SELECT * FROM employees LIMIT 0,5;
SELECT * FROM employees LIMIT 5;


#案例2:查詢第11條——第25條
SELECT * FROM employees LIMIT 10,15;


#案例3:有獎金的員工信息,並且工資較高的前10名顯示
SELECT * FROM employees 
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 10;

7、創建之後表的修改:ALTER TABLE

alter table 語句用於創建後對錶的修改, 基礎用法如下:

7.1、添加列(增加某個字段內容)

基本形式:

ALTER TABLE 表名 ADD 列名 列數據類型 [數據類型屬性] [after 插入位置];

# 對錶名這個表,增加一列(一個字段,並且指明瞭這個字段的數據類型),該字段在 某個插入位置(字段)後
# 如果沒有 [] 這個參數,默認新增字段,放在 最後

例子

ALTER TABLE students 
ADD address char(60);
# 在表的最後,新增一個字段,爲 address,其爲 一個字符串


ALTER TABLE students 
ADD birthday date 
AFTER age;
# 在名爲 age 的列(字段)後插入新的列 birthday(其數據類型爲 date)

7.2、修改列(修改字段名)

基本形式:

ALTER TABLE 表名 
CHANGE 列名稱 列新名稱 新數據類型 [數據類型屬性];

# 將原來的 字段,更改爲 新的字段(其數據類型也要指明)

例子

ALTER TABLE students 
CHANGE tel telphone char(13) default '-';
# 將原來的 tel 列名 改爲 telphone,其數據類型 和 屬性 都指明瞭


ALTER TABLE students 
CHANGE name name char(16) not null;
# 將 name 列的數據類型改爲 char(16)。這裏雖然是用改列,但實際上不是爲了改名,而是爲了改 列的數據類型

7.3、刪除列

基本形式:

ALTER TABLE 表名 DROP 列名稱;
# 將這列刪除(同時這一列對應下去的數據,也都刪除了)

例子

# 刪除 birthday 列:
ALTER TABLE students 
DROP birthday;

7.4、重命名錶

基本形式:

ALTER TABLE 表名 rename 新表名;
# 將原來的表名,更改爲 新表名

例子

ALTER TABLE students 
RENAME workmates;
# 重命名 students 表爲 workmates:

8、MySQL 導入/導出 數據

8.1、MySQL 導入數據

8.1.1、mysql 命令導入(整個數據庫導入)

使用 mysql 命令導入語法格式爲:

mysql -h 主機名 -u 用戶名 -p 密碼 < 要導入的數據庫數據(runoob.sql)

例子

mysql -u root -p 123456 < runoob.sql

將 runoob 作爲整個數據庫導入。

8.1.2、source 命令導入(整個數據庫導入)

source 命令導入數據庫需要先登錄到數庫終端:

mysql> create database abc;      # 創建數據庫
mysql> use abc;                  # 使用已創建的數據庫 
mysql> source /home/abc/abc.sql  
# 從abc.sql 導入整個數據庫進來

8.1.3、LOAD DATA導入數據(數據插入到 表中)

和 8.2.1 的導出數據互爲逆過程

以下實例中將從當前目錄中讀取文件 dump.txt ,將該文件中的數據插入到當前數據庫的 mytbl 表中

mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl;

如果指定 LOCAL 關鍵詞,則表明從客戶主機上按路徑讀取文件。如果沒有指定,則文件在服務器上按路徑讀取文件。

你能明確地在LOAD DATA語句中指出列值的分隔符和行尾標記(因爲可能之前保存成 txt 的時候,不是按默認保存),但是默認標記是定位符和換行符。

兩個命令的 FIELDS(註明列值分隔符) 和 LINES(行尾標記)。子句的語法是一樣的。兩個子句都是可選的,但是如果兩個同時被指定,FIELDS 子句必須出現在 LINES 子句之前。

mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl
  -> FIELDS TERMINATED BY ':'
  -> LINES TERMINATED BY '\r\n';
# 此時列值分隔符是 :
# 行尾標誌是 \r\n

LOAD DATA 默認情況下是按照數據文件中列的順序插入數據的,如果數據文件中的列與插入表中的列不一致,則需要指定列的順序。
如,在數據文件中的列順序是 a,b,c,但在插入表的列順序爲b,c,a,則數據導入語法如下:

mysql> LOAD DATA LOCAL INFILE 'dump.txt' 
    -> INTO TABLE mytbl (b, c, a);

8.2、MySQL 導出數據

8.2.1、SELECT ... INTO OUTFILE 語句導出數據(表中數據導出)

和 8.1.3 的導入數據 互爲逆過程

先要登陸到 MySQL 數據庫中。

其實就是,我們將 數據表 的數據,導出到文件中(比如 .txt 文件)

SELECT 列名 
FROM 表名 
INTO OUTFILE 導出文件的完整路徑;

其實就是,我們將從 表中讀數據,先讀取想要的數據(列名,可以是部分,也可以是全部),將其保存在 對應的 文件中即可

舉個例子

SELECT * 
FROM runoob_tbl 
INTO OUTFILE '/tmp/runoob.txt';
# 將 runoob_tbl 的所有內容(*) 導出,保存在 runoob.txt 文件中

保存的時候,因爲原本在表中,數據是一行一行的,那麼在保存的時候,默認列的隔開符和行尾符爲:定位符和換行符。(這裏和8.1.3 的導入數據對應上的

那麼如果我們想保存的時候,設置 列的隔開符 和 行尾符,可以用下面的語句來:

SELECT a,b,a+b 
FROM test_table;
INTO OUTFILE '/tmp/result.text'
FIELDS TERMINATED BY ',' [OPTIONALLY] ENCLOSED BY '"'
LINES TERMINATED BY '\n'

# SELECT 可以選擇,導出的數據是 部分字段,還是所有字段
# FIELDS 設置的是,列的隔開符
# LINES 是行尾符
# ENCLOSED 表示,文件中字符值放在 “” 之中
# 如果是 OPTIONALLY ENCLOSED,表示所有的值,都是用 “” 包起
# FIELDS 指定每一列的數據應該怎麼處理
# LINES 每一行之間怎麼處理
# 可以只出現其中幾個,也可全部一起;如果兩個同時被指定,FIELDS 子句必須出現在 LINES 子句之前。

注意的點

  • LOAD DATA INFILESELECT ... INTO OUTFILE的逆操作。爲了將一個數據庫的數據寫入一個文件,使用SELECT ... INTO OUTFILE,爲了將文件讀回數據庫,使用LOAD DATA INFILE。(和8.1.3 的導入數據對應上的
  • 該文件被創建到服務器主機上,因此您必須擁有FILE權限,才能使用此語法。
  • 輸出不能是一個已存在的文件。防止文件數據被篡改。
  • 你需要有一個登陸服務器的賬號來檢索文件。否則 SELECT … INTO OUTFILE 不會起任何作用(其實也就是要登陸到 數據庫中)
  • 在UNIX中,該文件被創建後是可讀的,權限由MySQL服務器所擁有。這意味着,雖然你就可以讀取該文件,但可能無法將其刪除。

8.2.2、mysqldump導出 SQL 格式的數據(可以導出單個表,也可以導出整個庫)

這些不用登陸到 MySQL 中

導出 SQL 格式的數據到指定文件,如下所示:

$ mysqldump -u root -p 庫名 庫中的表名 > dump.txt
password ******

如果你需要導出整個數據庫的數據,可以使用以下命令:

$ mysqldump -u root -p 庫名 > database_dump.txt
password ******

如果需要備份所有數據庫,可以使用以下命令:

$ mysqldump -u root -p --all-databases > database_dump.txt
password ******

8.2.3、將數據表及數據庫拷貝至其他主機

第一種方法

在本機導出之後,將文件發送給其他主機,然後在其他主機上,加載到其他主機的數據庫即可(先導出,再導入)

第二種方法:直接可以遠程導入,不需要先導出再導入,直接一次性處理完

命令將導出的數據直接導入到遠程的服務器上,但請確保兩臺服務器是相通的,是可以相互訪問的

$ mysqldump -u root -p 要導出的庫名 [表名] \
       | mysql -h 主機名 要導入的庫名
# 上面是 本機,發送給 另一臺主機
# 所以本機,就不用 -h,但是其他主機需要

利用了,管道


9、MySQL 腳本

腳本就是,將我們上面那些分散的那些指令,整個成一個文件 xxx.sql,然後運行這個 sql 腳本文件,就可以將指令執行。(類似於 shell 腳本,CPP 之類)

那麼如果執行 sql 文件(腳本)呢?

方法一:直接執行 sql 文件

mysql -h localhost -u root -p123456 < E:\mysql\test.sql

# 也就是,在登陸 MySQL 的時候,重定向輸入 這個 腳本文件,就可以運行了

方法二:先登錄 MySQL,再執行 sql 腳本文件(source)

mysql -h localhost -u root -p123456
# 先登錄進 MySQL 數據庫中

source E:\mysql\test.sql
# 接着,加載(執行) sql 腳本文件
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章