MySQL入門
MySQL 筆記
目錄
著名資料庫(瞭解)
公司 | 資料庫軟體 |
---|---|
IBM | DB2 |
微軟 | SQL Server、Access[1] |
Oracle | Oracle、MySQL |
Sybase | Sybase |
概念
- RDBMS(Ralational DataBase Management System)
= Manager + Database - Database = n tables
- table = 表結構 + 表關係
組成(瞭解即可)
- 資料查詢語言(DQL:Data Query Language):其語句也稱為“資料檢索語句”,用以從表中獲得資料,確定資料怎樣在應用程式給出。保留字SELECT是DQL(也是所有SQL)用得最多的動詞,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。這些DQL保留字常與其他型別的SQL語句一起使用。
- 資料操作語言(DML:Data Manipulation Language):其語句包括動詞INSERT,UPDATE和DELETE。它們分別用於新增,修改和刪除表中的行。也稱為動作查詢語言。
- 事務處理語言(TPL):它的語句能確保被DML語句影響的表的所有行及時得以更新。TPL語句包括BEGIN TRANSACTION,COMMIT和ROLLBACK。
- 資料控制語言(DCL):它的語句通過GRANT或REVOKE獲得許可,確定單個使用者和使用者組對資料庫物件的訪問。某些RDBMS可用GRANT或REVOKE控制對錶單個列的訪問。
- 資料定義語言(DDL):其語句包括動詞CREATE和DROP。在資料庫中建立新表或刪除表(CREAT TABLE 或 DROP TABLE);為表加入索引等。
- 指標控制語言(CCL):其語句,像DECLARE CURSOR,FETCH INTO和UPDATE WHERE CURRENT用於對一個或多個表單行的操作。
注意點
- MySQL中不區分大小寫,但建議關鍵字全大寫,資料庫、表名等全小寫,以提高可讀性
- MySQL進行
WHERE
條件匹配、ORDER By
排序時預設不區分大小寫。若需區分大小寫,可在字串前增加BINARY
- 清屏命令:Linux上
system clear
;Windows上system cls
(需要MySQL 8以上)
DDL操作
操作資料庫
- 顯示資料庫:
SHOW DATABASES;
- 選擇資料庫:
USE 表名;
- 建立資料庫:
CREATE DATABASE [IF NOT EXISTS] 表名 [CHARSET=utf8];
- 刪除資料庫:
DROP DATABASE [IF EXISTS] 表名;
- 修改資料庫編碼:
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 |
... | ... |
操作表
-
顯示錶:
SHOW TABLES;
-
顯示錶結構:
DESC 表名;
-
建立表
CREATE TABLE [IF NOT EXISTS] 表名( 列名 列型別, 列名 列型別, ... 列名 列型別 );
-
刪除表:
DROP TABLE [IF EXISTS] 表名;
-
修改表(字首:
ALTER TABLE 表名
):-
新增列
ALTER TABLE 表名 ADD( 列名 列型別, 列名 列型別, ... 列名 列型別 );
-
刪除列:
ALTER TABLE 表名 DROP 列名;
-
修改列型別:
ALTER TABLE 表名 MODIFY 列名 列型別;
-
修改列名:
ALTER TABLE 表名 CHANGE 原列名 新列名 列型別;
-
修改表名稱:
ALTER TABLE 表名 RENAME TO 新表名;
-
DML(Data Manipulation Language)
- 插入一行record
INSERT INTO 表名(列名1, 列名2, 列名3, ...) VALUES(值1, 值2, 值3, ...)
→不要求包含所有列及列順序INSERT INTO 表名 VALUES(值1, 值2, 值3, ...)
→ 要求包含所有列,且按預設順序
- 修改資料
UPDATE 表名 SET 列名=值 WHERE 條件
(如果沒有where部分則會修改所有行)- 條件為boolean值,運算子有
=
、!=
、<>
、<
、>
、<=
、>=
、BETWEEN ... AND ...
(包含開始和結束值) 、IN(...)
、IS NULL
、NOT
(MySQL中NOT
只限用於IN
、BETWEEN
、EXISTS
取反)、AND
、OR
(注意: 判斷是否為NULL
不能用= NULL
,而必須用IS NULL
;AND
優先順序高於OR
)
- 刪除資料
DELETE FROM 表名 WHERE 條件
(如果沒有WHERE則刪除表中所有資料!)
DCL(Data Control Language)
-
一個專案建立一個使用者,只對應一個數據庫,這個使用者只能對這個資料庫有許可權,其他資料庫無法操作
-
建立使用者
CREATE USER 使用者名稱@IP(或localhost) IDENTIFIED BY '密碼'; -- 使用者只能在指定的IP上登入 CREATE USER 使用者名稱@'%' IDENTIFIED BY '密碼'; -- 使用者可以在任意IP上登入
-
給使用者授權
GRANT 許可權1[, 許可權2, ...] ON 資料庫.* TO 使用者名稱@地址 # 例: GRANT SELECT, CREATE, ALTER, DROP, INSERT, UPDATE, DELETE ON mydb1.* TO user1@localhost; GRANT ALL ON 資料庫.* TO 使用者名稱@IP地址
-
撤銷授權
REVOKE 許可權1[, 許可權2, ...] ON 資料庫.* FROM 使用者名稱@IP地址;
-
檢視許可權
SHOW GRANTS ON 使用者名稱@IP地址;
-
刪除使用者
DROP USER 使用者名稱@IP地址;
DQL(Data Query Language)
查詢不會修改資料庫表記錄
-
欄位(列)控制
-
查詢所有列
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]
-
文字處理函式
函式 說明 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中的位置 -
時間處理函式
函式 說明 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)時間 -
數值處理函式
函式 說明 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;
-
-
條件控制
-
條件查詢 (新增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)- 先按第一個條件排序,第一個條件相同時,按第二個條件,依此類推。
-
聚合查詢:利用聚合函式縱向查詢某一列的非空行數
COUNT
、SUM
、MAX
、MIN
、AVG
注意: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行資料
-
編碼
-
顯示編碼方式
SHOW VARIABLES LIKE 'char%';
-
設定編碼方式:
- 若在互動視窗修改,則僅當次有效,退出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
備份與恢復
- 備份
- 在cmd中使用
mysqldump -u使用者 -p[密碼] 資料庫名> 儲存路徑(含檔名)
如:mysqldump -uroot -p123 mydb1 > C:/a.sql
- 只是保持資料庫內容,不儲存資料庫本身。後期恢復時需要先
CREATE DATABASE
- 在cmd中使用
- 恢復
- 若資料庫不存在,需要先建立
- 方式1:cmd輸入
mysql -u使用者 -p 資料庫名 < 匯入sql檔案路徑(含檔名)
如:mysql -uroot -p123 mydb1 < C:/a.sql
- 方式2:mysql視窗使用source 匯入的sql檔案路徑
如:source C:/a.sql
約束
主鍵約束
-
含義:唯一標識一行記錄的列元素(不建議用自然主鍵,如身份證號,避免後期出錯)
-
特點:
- 非空
- 唯一
- 可以被引用(外來鍵)
-
使用方式
# 建立表時指定的兩種方式: 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;
-
自增長
- 自動在前一個記錄的基礎上,該列數值加1(要求該列必須為INT型)
- 分散式系統中不建議自增長,可改用UUID
CREATE TABLE emp( empno INT PRIMARY KEY AUTO_INCREMENT, ename VARCHAR(50) )
非空約束和唯一約束
-
非空約束
NOT NULL
,唯一約束UNIQUE
CREATE TABLE emp( empno INT PRIMARY KEY, ename VARCHAR(50) NOT NULL UNIQUE )
外來鍵
-
關係模型:
- 一對一(較少見)
- 一對多
- 多對多
-
外來鍵特點:
- 外來鍵必須引用本表或另一張表的主鍵(多方引用一方)
- 外來鍵可以為空、可以重複,但所引用的值必須存在
- 一張表中可以存在多個外來鍵
-
建立方式
-
一對多
-- 建立時定義: 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;
連線查詢(一次查詢多張表)
多表查詢注意使用表名對列進行限定
-
內連線(從多張表的笛卡爾積[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
- 方言:
-
外連線
- 左外連線
- 左表無論是否滿足條件都會查詢出來(至少顯示1次),而右表只有滿足條件才能出來。左表中不滿足條件的記錄,右表部分均為
NULL
SELECT * FROM 表1 別名1 LEFT OUTER JOIN 表2 別名2 ON 別名1.xx = 別名2.xx
- 左表無論是否滿足條件都會查詢出來(至少顯示1次),而右表只有滿足條件才能出來。左表中不滿足條件的記錄,右表部分均為
- 右外連線:
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
- 左外連線
-
子查詢(查詢中嵌入查詢,需要包裹在圓括號中)
-
SELECT語句出現在WHERE之後,作為條件存在
-
單行單列:作為值存在,可用
=
、!=
、<>
、<
、>
、<=
、>=
比較SELECT * FROM 表1 別名1 WHERE 列1 [=、!=、>、<、>=、<=] (SELECT 列 FROM 表2 別名2 WHERE 條件);
-
```mysql -- 例:查詢公司中工資最高的員工資訊 SELECT * FROM emp WHERE sal = (SELECT MAX(sal) FROM emp);
-
多行單列:作為多個值存在,可在括號前加
ALL
、ANY
、IN
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 條件
-