1. 程式人生 > 實用技巧 >MySQL入門

MySQL入門

MySQL 筆記

目錄

著名資料庫(瞭解)

公司 資料庫軟體
IBM DB2
微軟 SQL Server、Access[1]
Oracle Oracle、MySQL
Sybase Sybase

概念

  1. RDBMS(Ralational DataBase Management System)
    = Manager + Database
  2. Database = n tables
  3. table = 表結構 + 表關係

組成(瞭解即可)

  1. 資料查詢語言(DQL:Data Query Language):其語句也稱為“資料檢索語句”,用以從表中獲得資料,確定資料怎樣在應用程式給出。保留字SELECT是DQL(也是所有SQL)用得最多的動詞,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。這些DQL保留字常與其他型別的SQL語句一起使用。
  2. 資料操作語言(DML:Data Manipulation Language):其語句包括動詞INSERT,UPDATE和DELETE。它們分別用於新增,修改和刪除表中的行。也稱為動作查詢語言。
  3. 事務處理語言(TPL):它的語句能確保被DML語句影響的表的所有行及時得以更新。TPL語句包括BEGIN TRANSACTION,COMMIT和ROLLBACK。
  4. 資料控制語言(DCL):它的語句通過GRANT或REVOKE獲得許可,確定單個使用者和使用者組對資料庫物件的訪問。某些RDBMS可用GRANT或REVOKE控制對錶單個列的訪問。
  5. 資料定義語言(DDL):其語句包括動詞CREATE和DROP。在資料庫中建立新表或刪除表(CREAT TABLE 或 DROP TABLE);為表加入索引等。
  6. 指標控制語言(CCL):其語句,像DECLARE CURSOR,FETCH INTO和UPDATE WHERE CURRENT用於對一個或多個表單行的操作。

注意點

  1. MySQL中不區分大小寫,但建議關鍵字全大寫,資料庫、表名等全小寫,以提高可讀性
  2. MySQL進行WHERE條件匹配、ORDER By排序時預設不區分大小寫。若需區分大小寫,可在字串前增加BINARY
  3. 清屏命令:Linux上system clear;Windows上system cls (需要MySQL 8以上)

DDL操作

操作資料庫

  1. 顯示資料庫:SHOW DATABASES;
  2. 選擇資料庫:USE 表名;
  3. 建立資料庫:CREATE DATABASE [IF NOT EXISTS] 表名 [CHARSET=utf8];
  4. 刪除資料庫:DROP DATABASE [IF EXISTS] 表名;
  5. 修改資料庫編碼:ALTER DATABASE 表名 CHARACTER SET utf8;

資料型別(列型別)

必須為每一列指定資料型別

注意:MySQL中字串只能加單引號

資料型別 說明
int 整型
double(5,2) 浮點型,5表示最大總位數(不包括小數點),2表示小數點後位數
decimal 浮點型,不損失精度,表單中錢用得較多
char(255) 固定長度字元,長度不足時補足,超出長度報錯。最大支援255個位元組
varchar(65535) 變長字元,長度不足時不補足,超長報錯。最大支援65535 bytes。會額外使用1個位元組儲存長度資訊
text 不在SQL標準中(標準裡的是clob),分tinytext (2^8^-1,255B)、text (2^16^-1,65k)、mediumtext (2^24^-1,16M)、longtext (2^32^-1,4G)
blob 用於儲存二進位制資料,分tinyblob (2^8^-1)、blob (2^16^-1)、mediumblob (2^24^-1)、longblob (2^32^-1)
date 格式:YYYY-MM-DD
time 格式:hh:mm:ss
timestamp date + time
... ...

操作表

  1. 顯示錶:SHOW TABLES;

  2. 顯示錶結構:DESC 表名;

  3. 建立表

    CREATE TABLE [IF NOT EXISTS] 表名(
    	列名 列型別,
    	列名 列型別,
    	...
    	列名 列型別
    );
    
  4. 刪除表:DROP TABLE [IF EXISTS] 表名;

  5. 修改表(字首:ALTER TABLE 表名):

    • 新增列

      ALTER TABLE 表名 ADD(
      	列名 列型別,
      	列名 列型別,
      	...
      	列名 列型別
      );
      
    • 刪除列:ALTER TABLE 表名 DROP 列名;

    • 修改列型別:ALTER TABLE 表名 MODIFY 列名 列型別;

    • 修改列名:ALTER TABLE 表名 CHANGE 原列名 新列名 列型別;

    • 修改表名稱:ALTER TABLE 表名 RENAME TO 新表名;

DML(Data Manipulation Language)

  1. 插入一行record
    • INSERT INTO 表名(列名1, 列名2, 列名3, ...) VALUES(值1, 值2, 值3, ...) →不要求包含所有列及列順序
    • INSERT INTO 表名 VALUES(值1, 值2, 值3, ...) → 要求包含所有列,且按預設順序
  2. 修改資料
    • UPDATE 表名 SET 列名=值 WHERE 條件 (如果沒有where部分則會修改所有行)
    • 條件為boolean值,運算子有 =!=<><><=>=BETWEEN ... AND ...(包含開始和結束值) 、IN(...)IS NULLNOT(MySQL中NOT只限用於INBETWEENEXISTS取反)、ANDOR注意: 判斷是否為NULL不能用= NULL,而必須用IS NULLAND優先順序高於OR
  3. 刪除資料
    • DELETE FROM 表名 WHERE 條件(如果沒有WHERE則刪除表中所有資料!)

DCL(Data Control Language)

  1. 一個專案建立一個使用者,只對應一個數據庫,這個使用者只能對這個資料庫有許可權,其他資料庫無法操作

  2. 建立使用者

    CREATE USER 使用者名稱@IP(或localhost) IDENTIFIED BY '密碼';
    -- 使用者只能在指定的IP上登入
    CREATE USER 使用者名稱@'%' IDENTIFIED BY '密碼';
    -- 使用者可以在任意IP上登入
    
  3. 給使用者授權

    GRANT 許可權1[, 許可權2, ...] ON 資料庫.* TO 使用者名稱@地址
    # 例: GRANT SELECT, CREATE, ALTER, DROP, INSERT, UPDATE, DELETE ON mydb1.* TO user1@localhost;
    GRANT ALL ON 資料庫.* TO 使用者名稱@IP地址
    
  4. 撤銷授權

    REVOKE 許可權1[, 許可權2, ...] ON 資料庫.* FROM 使用者名稱@IP地址;
    
  5. 檢視許可權 SHOW GRANTS ON 使用者名稱@IP地址;

  6. 刪除使用者 DROP USER 使用者名稱@IP地址;

DQL(Data Query Language)

查詢不會修改資料庫表記錄

  1. 欄位(列)控制

    • 查詢所有列 SELECT * FROM 表名;

    • 查詢指定列 SELECT 列1[, 列2, ...] FROM 表名;

    • 完全重複的記錄只顯示一次 SELECT DISTINCT * | 列1[, 列2, ...] FROM 表名;

    • 列運算

      • 數值型別的列可以做加、減、乘、除運算,如SELECT *,salary*1.5 FROM mydb1;,非數值型別按0處理,NULL值與任何值運算都得到NULL

      • 字串連線用CONCAT(str1, str2, ...)函式(其他多數DBMS採用+||連線字串)

      • NULL與任何值運算、連線字串都得NULL,處理NULL值可用IFNULL(列名, 預設值)替換NULL值為預設值

      • LTRIM(字串) 可以刪除字串左側空格,RTRIM為右側,TRIM為兩側

      • 可用不加FROM的語句SELECT 列運算式 進行測試運算,如

        SELECT 2*3;
        SELECT Trim(' abc ');
        SELECT Now(); #返回當前日期和時間
        
      • 其他函式[2]

        1. 文字處理函式

          函式 說明
          Left(str, len) / Right(str, len) 返回字串左側 / 右側len個字元
          Length(str) 返回字串長度
          LTrim(str) / RTrim(str) / Trim(str) 刪除字串左 / 右 / 兩側字串
          Soundex(str) 返回str的soundex值(發音)
          Lower(str) / Upper(str) 轉換字串為小寫 / 大寫
          Substring(str, n, len) 返回第n個字元(包含)開始的len個字元的字串,n為負值時表示倒數第n個
          Locate(substr, str) 返回字串第一次出現在str中的位置
        2. 時間處理函式

          函式 說明
          CurDate() / CurTime() / Now() 返回當前日期 / 時間 / 日期時間
          Date(datetime) / Time(datetime) 提取日期時間的日期部分 / 時間部分
          Year(dt) / Month(dt) / Day(dt) 返回日期時間的年 / 月 / 日
          Hour(dt) / Minute(dt) / Second(dt) 返回日期時間的時 / 分 / 秒
          DayOfWeek(dt) 返回星期幾(星期日為1,星期六為7)
          DateDiff(end_dt, start_dt) 返回兩日期時間差
          AddDate(dt,INTERVAL expr type) 增加一個expr type日期和時間
          AddTime(dt, expr) 增加一個expr(hh:mm:ss)時間
        3. 數值處理函式

          函式 說明
          Sin(x) / Cos(x) / Tan(x) 正弦值 / 餘弦值 / 正切值
          Abs(x) 絕對值
          Pi() 圓周率
          Mod() 模運算,相當於%
          Rand() 返回0~1之間的隨機數
          Sqrt(x) 平方根
          Exp(x) 求自然常數e的x次方
      • 更多函式及用法可參閱:MySQL常用函式大全

    • 起別名:(AS 可以省略),也可用於給表起別名

      SELECT 列名 (AS) 別名 FROM 表名; # as關鍵字可以省略
      # 如 SELECT salary*1.5 as 工資 FROM employees;
      
  2. 條件控制

    • 條件查詢 (新增WHERE條件)

    • 模糊查詢:通過LIKE關鍵字和_%萬用字元實現(_匹配一個字元;%匹配0到n個字元,但不匹配NULL)

      • 模糊搜尋的時間開銷相比一般條件查詢更大
      • 不要過度使用萬用字元,若能用其他操作符實現,應使用其他操作符
      • 使用萬用字元時,除非絕對有必要,否則不要將萬用字元放置在搜尋模式的開始處,這樣搜尋起來最慢
      SELECT * FROM employees WHERE name LIKE '張%'; #匹配如張、張三、張某某
      SELECT * FROM employees WHERE name LIKE '張__';  # 匹配如張某某,但不匹配張三
      
    • 正則表示式:通過 REGEXP 匹配字串 實現

      • 與LIKE的區別:LIKE是整行匹配;REGEXP只要行內字串滿足匹配字串即可,若匹配字串首尾同時新增 ^$ 則變成整行匹配

      • 與多數其他軟體不同,匹配特殊字元,如.[]()|等,需要新增兩個反斜槓\\,如\\.\\n\\\(匹配 \ 本身)、\\1(反向引用)等(一個 \ 自己解釋一個,正則表示式庫解釋另一個)

      • 字元類

        說明
        [:alpha:] 任意字元(同[a-zA-Z]
        [:digit:] 任意數字(同[0-9]
        [:alnum:] 任意字元和數字(同[a-zA-Z0-9]
        [:xdigit:] 任意十六進位制數字(同[a-fA-F0-9]
        [:lower:] 任意小寫字母(同[a-z]
        [:upper:] 任意大寫字母(同[A-Z]
        [:blank:] 空格和製表符(同[ \\t])
        [:space:] 包含空格在內的任意空白字元(同[\\f\\n\\r\\t\\v]
        [:print:] 任意可列印字元
        [:graph:] 除空格外的任意可列印字元
        [:cntrl:] ASCII控制字元(ASCII 0-31和127)
        [:punct:] 即不在[:alnum:],也不在[:cntrl:]中的字元
      • 正則表示式內容較多,用法可參見 正則表示式30分鐘入門教程

      • MySQL中可用SELECT '待匹配字串' REGEXP '匹配樣式字串' 簡單測試(結果1為匹配,0為不匹配)

    • 排序:ORDER BY 列名1 [ASC/DESC], ... (ASC升序,DESC降序,省略時預設ASC)

      • 先按第一個條件排序,第一個條件相同時,按第二個條件,依此類推。
    • 聚合查詢:利用聚合函式縱向查詢某一列的非空行數COUNTSUMMAXMINAVG
      注意:

      • COUNT(列名) 記錄該列非NULL的行數,若為COUNT(*) 則為包含NULL的所有行數;
      • 聚合查詢一般忽略NULL值
      • 函式引數可為 DISTINCT 列名,此時重複值只計算一次
      SELECT COUNT(salary) 計數,SUM(DISTINCT salary) 總和, MAX(salary) 最高, MIN(salary) 最低, AVG(salary) 平均 
      FROM employees 
      WHERE department = '財務部';
      
    • 分組查詢 GROUP BY -- 只用於查詢組資訊

      • 用法:SELECT 列名1[,列名2,...], 聚合函式 FROM 表名 GROUP BY 列名1[,列名2,...]`
      • GROUP BY前通過WHERE 列條件過濾行,之後則使用HAVING 關鍵字過濾組資訊(除位置外,HAVING用法與WHERE基本相同)
      • GROUP BY 列 可接WITH ROLLUP,增加一行彙總行
      • 結果不一定有序,最好結合ORDER BY
      -- 列出各個崗位裡工資大於15000的人數,且滿足要求的崗位人數必須大於1人
      SELECT job, COUNT(job) FROM employees 
      WHERE salary > 15000 
      GROUP BY job 
      HAVING count(job) > 1;
      
    • MySQL方言之LIMIT(僅MySQL支援)

      • LIMIT [row - 1,] n 顯示從第row行(下標0為第一行)開始的n行資料

編碼

  1. 顯示編碼方式 SHOW VARIABLES LIKE 'char%';

  2. 設定編碼方式:

    • 若在互動視窗修改,則僅當次有效,退出mysql即恢復原樣;若在my.ini中修改,則為永久生效
    /* 互動視窗修改 */
    SET character_set_client=utf8; #設定客戶端編碼方式
    SET character_set_results=utf8; #設定mysql返回的資料編碼格式
    
    /* my.ini中修改 */
    default-character-set=utf8 # 修改預設字符集,包括client、results、server
    character-set-server=utf8
    

備份與恢復

  1. 備份
    • 在cmd中使用mysqldump -u使用者 -p[密碼] 資料庫名> 儲存路徑(含檔名)
      如:mysqldump -uroot -p123 mydb1 > C:/a.sql
    • 只是保持資料庫內容,不儲存資料庫本身。後期恢復時需要先CREATE DATABASE
  2. 恢復
    • 若資料庫不存在,需要先建立
    • 方式1:cmd輸入mysql -u使用者 -p 資料庫名 < 匯入sql檔案路徑(含檔名)
      如:mysql -uroot -p123 mydb1 < C:/a.sql
    • 方式2:mysql視窗使用source 匯入的sql檔案路徑
      如:source C:/a.sql

約束

主鍵約束

  1. 含義:唯一標識一行記錄的列元素(不建議用自然主鍵,如身份證號,避免後期出錯)

  2. 特點:

    • 非空
    • 唯一
    • 可以被引用(外來鍵)
  3. 使用方式

    # 建立表時指定的兩種方式:
    CREATE TABLE emp(
    	empno INT PRIMARY KEY,
        ename VARCHAR(50)
    )
    
    CREATE TABLE emp(
    	empno INT,
        ename VARCHAR(50),
        PRIMARY KEY(empno)
    )
    
    # 通過修改表指定/刪除
    ALTER TABLE emp ADD PRIMARY KEY(empno);
    ALTER TABLE emp DROP PRIMARY KEY;
    
  4. 自增長

    • 自動在前一個記錄的基礎上,該列數值加1(要求該列必須為INT型)
    • 分散式系統中不建議自增長,可改用UUID
    CREATE TABLE emp(
    	empno INT PRIMARY KEY AUTO_INCREMENT, 
        ename VARCHAR(50)
    )
    

非空約束和唯一約束

  1. 非空約束NOT NULL,唯一約束UNIQUE

    CREATE TABLE emp(
    	empno INT PRIMARY KEY, 
        ename VARCHAR(50) NOT NULL UNIQUE
    )
    

外來鍵

  1. 關係模型:

    • 一對一(較少見)
    • 一對多
    • 多對多
  2. 外來鍵特點:

    • 外來鍵必須引用本表或另一張表的主鍵(多方引用一方)
    • 外來鍵可以為空、可以重複,但所引用的值必須存在
    • 一張表中可以存在多個外來鍵
  3. 建立方式

    • 一對多

      -- 建立時定義:
      CREATE TABLE emp(
      	empno INT PRIMARY KEY, # 職員編號
          ename VARCHAR(50), # 職員姓名
          dept_no INT, # 所屬部門
          CONSTRAINT 自定義約束名 FOREIGN KEY(dept_no) REFERENCES dept(deptno); 
          # 引用dept表的deptno列
      )
      -- 修改已有列:
      ALTER TABLE emp 
      ADD CONSTRAINT 自定義約束名 FOREIGN KEY(dept_no) REFERENCES dept(deptno);
      
    • 一對一

      CREATE TABLE husband(
      	hid INT PRIMARY KEY AUTO_INCREMENT,
          hname VARCHAR(50)
      )
      CREATE TABLE wife(
      	wid INT PRIMARY KEY AUTO_INCREMENT,
          wname VARCHAR(50),
          CONSTRAINT fk_wife_hus FOREIGN KEY(wid) REFERENCES husband(hid)
      )
      # wid對應hid。由於wid為主鍵,故唯一非空。wid又為husband表外來鍵(引用hid),故引用值必須存在。由此可實現一對一關係
      
    • 多對多
      需要藉助第三張表作為關聯表,記錄兩張表主鍵的關係

      CREATE TABLE teacher(
      	tid INT PRIMARY KEY AUTO_INCREMENT, # 老師ID
          name VARCHAR(50)
      )
      CREATE TABLE student(
      	sid INT PRIMARY KEY AUTO_INCREMENT, # 學生ID
          name VARCHAR(50)
      )
      CREATE TABLE tie(  # 關聯表
          tid INT,
      	sid INT,
          CONSTRAINT fk_tea FOREIGN KEY(tid) REFERENCES teacher(tid)
          CONSTRAINT fk_stu FOREIGN KEY(sid) REFERENCES student(sid)
      )
      

多表查詢

合併結果集

  • 用於將兩個結果集拼接在一起顯示

  • 要求結果集列數&列型別相同

  • 語法: (通過UNION [ALL] 拼接多個SELECT ... FROM ... 語句,不加ALL會對緊鄰的兩個結果集的行進行去重)

    CREATE TABLE ab(a INT, b VARCHAR(50));
    CREATE TABLE cd(c INT, d VARCHAR(50));
    ...  # 此處新增資料
    SELECT * FROM ab UNION ALL SELECT * FROM cd;
    SELECT a FROM ab UNION SELECT c FROM cd UNION ALL SELECT a FROM ab;
    

連線查詢(一次查詢多張表)

多表查詢注意使用表名對列進行限定

  1. 內連線(從多張表的笛卡爾積[3]中篩選出滿足條件的表)

    • 方言:SELECT * FROM 表1 別名1, 表2 別名2 WHERE 別名1.xx = 別名2.xx
    • 標準(推薦):SELECT * FROM 表1 別名1 INNER JOIN 表2 別名2 ON 別名1.xx = 別名2.xx
      • 大於兩張表連線時,每連線一張表,後面就用ON條件限定一次。若有WHERE條件,則放在所有連線之後
    • 自然(可讀性降低):SELECT * FROM 表1 別名1 NATURAL JOIN 表2 別名2 (由系統自動根據兩表相同的列名連線)
    # 查詢滿足條件的所有員工的名稱、工資、及所在部門資訊
    # 方言
    SELECT ename, salary, dname
    FROM emp e, dept d
    WHERE e.deptno = d.deptno
    # 標準
    SELECT ename, salary, dname
    FROM emp e INNER JOIN dept d
    ON e.deptno = d.deptno
    # 自然
    SELECT ename, salary, dname
    FROM emp e NATURAL JOIN dept d
    
  2. 外連線

    • 左外連線
      • 左表無論是否滿足條件都會查詢出來(至少顯示1次),而右表只有滿足條件才能出來。左表中不滿足條件的記錄,右表部分均為NULL
      • SELECT * FROM 表1 別名1 LEFT OUTER JOIN 表2 別名2 ON 別名1.xx = 別名2.xx
    • 右外連線:SELECT * FROM 表1 別名1 RIGHT OUTER JOIN 表2 別名2 ON 別名1.xx = 別名2.xx
    • 全外連線
      • 左右表記錄無論是否滿足條件都至少顯示一次,不滿足條件的,另一部分補NULL
      • MySQL中不支援,但可以通過UNION連線左外連線和右外連線得到
    • 左外自然連線和右外自然連線(不需要寫ON條件):NATURAL LEFT/RIGHT OUTER JOIN
    • 大於兩張表連線時,每連線一張表,後面就用ON條件限定一次。若有WHERE條件,則放在所有連線之後
    # 查詢所有員工的名稱、工資、及所在部門資訊(無論員工是否滿足條件)
    SELECT ename, salary, dname
    FROM emp e LEFT OUTER JOIN dept d #左外連線
    ON e.deptno = d.deptno
    
    # 顯示所有部門的名稱,及部門職工名稱、工資(無論部門是否滿足條件)
    SELECT ename, salary, dname
    FROM emp e RIGHT OUTER JOIN dept d #右外連線
    ON e.deptno = d.deptno
    
    # 全外連線
    SELECT ename, salary, dname
    FROM emp e LEFT OUTER JOIN dept d
    ON e.deptno = d.deptno
    UNION  #不加ALL以去重
    SELECT ename, salary, dname
    FROM emp e RIGHT OUTER JOIN dept d
    ON e.deptno = d.deptno
    
  3. 子查詢(查詢中嵌入查詢,需要包裹在圓括號中)

    • SELECT語句出現在WHERE之後,作為條件存在

      • 單行單列:作為值存在,可用 =!=<><><=>=比較

        SELECT * FROM 表1 別名1 
        WHERE 列1 [=、!=、>、<、>=、<=] (SELECT 列 FROM 表2 別名2 WHERE 條件);
        
    
       ```mysql
        -- 例:查詢公司中工資最高的員工資訊
       SELECT * FROM emp 
    WHERE sal = (SELECT MAX(sal) FROM emp);
    
    • 多行單列:作為多個值存在,可在括號前加ALLANYIN

      SELECT * FROM 表1 別名1 
      WHERE 列1 [ALL、ANY、IN] (SELECT 列 FROM 表2 別名2 WHERE 條件);
      
    • 單行多列:作為一個物件存在

       SELECT * FROM 表1 別名1 
       WHERE (列1,列2) IN (SELECT 列1,列2 FROM 表2 別名2 WHERE 條件);
    
    • SELECT語句出現在FROM之後,作為表存在(多行多列)

      SELECT * FROM 表1 別名1, (SELECT ...) 別名2 WHERE 條件
      

  1. Access為桌面型資料庫,主要用於區域網;其餘的為C/S型(客戶端/伺服器型) ↩︎

  2. 函式在不同DBMS間可移植性較差,編寫sql指令碼時最好標註清楚 ↩︎

  3. 笛爾積:{a, b, c} x {1, 2} = {a1, a2, b1, b2, c1, c2} ↩︎