mysql
數據處理
Tedu Python 教學部 |
---|
Author:呂澤 |
數據處理數據處理1. 文件處理1.1 引入1.2 文件讀寫操作1.2.1 打開文件1.2.2 讀取文件1.2.3 寫入文件1.2.4 關閉文件1.2.5 with操作1.2.6 緩衝區1.2.7 文件偏移量1.3 os模組2. 正則表達式2.1 概述2.2 元字元使用2.3 匹配規則2.3.1 特殊字元匹配2.3.2 貪婪模式和非貪婪模式2.3.3 正則表達式分組2.3.4 正則表達式匹配原則2.4 Python re模組使用2.4.1 基礎函數使用2.4.2 生成match對象2.4.3 match對象使用2.4.4 flags參數擴展3. 資料庫3.1概述3.2 MySQL3.3 SQL語言3.4 資料庫管理3.5 數據表管理3.5.1 基礎數據類型3.5.2 表的基本操作3.6 表數據基本操作3.5.1 插入(insert)3.6.2 查詢(select)3.6.3 where子句3.6.4 更新表記錄(update)3.6.5 刪除表記錄(delete)3.6.6 表欄位的操作(alter)3.5.7 時間類型數據3.7 高級查詢語句3.8 聚合操作3.8.1 聚合函數3.8.2 聚合分組3.8.3 聚合篩選3.8.4 去重語句3.8.5 聚合運算3.9 索引操作3.9.1 概述3.9.2 索引分類3.9.3 索引創建3.10 外鍵約束和表關聯關係3.10.1 外鍵約束3.10.2 表關聯設計3.10.3 E-R模型3.10.4 表連接3.11 視圖3.12 函數和存儲過程3.12.1 函數創建3.12.2存儲過程創建3.12.3 存儲過程和存儲函數操作3.12.4 函數和存儲過程區別3.13 事務控制3.13.1 事務概述3.13.2 事務操作3.13.3 事務四大特性3.13.4 事務隔離級別3.14 資料庫優化3.14.1 資料庫設計範式3.14.2 MySQL存儲引擎3.14.3 欄位數據類型選擇3.14.4 鍵的設置3.14.5 explain語句3.14.6 SQL優化3.14.7 表的拆分3.15 資料庫備份和用戶管理3.15.1 表的複製3.15.2 數據備份3.15.3 用戶許可權管理3.16 pymysql模組
數據處理
-
數據處理概述
數據處理的基本目的是從大量的、可能是雜亂無章的、難以理解的數據中抽取並推導出對於某些特定的人們來說是有價值、有意義的數據。當下數據處理貫穿於社會生產和社會生活的各個領域。數據處理技術的發展及其應用的廣度和深度,極大地影響了人類社會發展的進程。數據處理也是大數據,數據分析等後續科學的基本環節。
-
基本概念
- 數據 : 能夠輸入到電腦中並被識別處理的資訊集合。
- 大數據:是指無法在一定時間範圍內用一定工具進行捕捉、管理和處理的數據集合,是海量、高增長率和多樣化的資訊資產。
-
數據存儲階段
-
人工管理階段:人為管理,沒有固定的格式和存儲方法,容易混亂。
-
文件管理階段 :數據可以長期保存,存儲數據量大,使用簡單。
-
資料庫管理階段:高效,可以存儲更大量數據,便於管理,更加專業。
-
1. 文件處理
1.1 引入
-
什麼是文件
文件是保存在持久化存儲設備(硬碟、U盤、光碟..)上的一段數據,一個文本,一個py
文件,一張圖片,一段視······ 這些都是文件。
-
文件分類
- 文本文件:打開後會自動解碼為字元,如txt文件,word文件,py程式文件。
- 二進位文件:內部編碼為二進位碼,無法通過文字編碼解析,如壓縮包,音頻,影片,圖片等。
-
位元組串類型
-
概念 : 在python3中引入了位元組串的概念,與str不同,位元組串以位元組序列值表達數據,更方便用來處理二進程數據。
-
字元串與位元組串相互轉化方法
x1- 普通的英文字元字元串常量可以在前面加b轉換為位元組串,例如:b'hello'
2- 變數或者包含非英文字元的字元串轉換為位元組串方法 :str.encode()
3- 位元組串轉換為字元串方法 : bytes.decode()
4
5注意:python字元串用來表達utf8字元,因為並不是所有二進位內容都可以轉化為utf8字元,所以不是所有位元組串都能轉化為字元串,但是所有字元串都能轉化成二進位,所以所有字元串都能轉換為位元組串。
-
1.2 文件讀寫操作
使用程式操作文件,無外乎對文件進行讀或者寫
- 讀 :即從文件中獲取內容
- 寫 :即修改文件中的內容
對文件實現讀寫的基本操作步驟為:打開文件,讀寫文件,關閉文件。
1.2.1 打開文件
xxxxxxxxxx
file_object = open(file_name, access_mode='r', buffering=-1,encoding=None)
功能:打開一個文件,返回一個文件對象。
參數:file_name 文件名;
access_mode 打開文件的方式,如果不寫默認為『r』
buffering 1表示有行緩衝,默認則表示使用系統默認提供的緩衝機制。
encoding='UTF-8' 設置打開文件的編碼方式,一般Linux下不需要
返回值:成功返迴文件操作對象。
打開模式 | 效果 |
---|---|
r | 以讀方式打開,文件必須存在 |
w | 以寫方式打開,文件不存在則創建,存在清空原有內容 |
a | 以追加模式打開,文件不存在則創建,存在則繼續進行寫操作 |
r+ | 以讀寫模式打開 文件必須存在 |
w+ | 以讀寫模式打開文件,不存在則創建,存在清空原有內容 |
a+ | 追加並可讀模式,文件不存在則創建,存在則繼續進行寫操作 |
rb | 以二進位讀模式打開 同r |
wb | 以二進位寫模式打開 同w |
ab | 以二進位追加模式打開 同a |
rb+ | 以二進位讀寫模式打開 同r+ |
wb+ | 以二進位讀寫模式打開 同w+ |
ab+ | 以二進位讀寫模式打開 同a+ |
注意 :
- 以二進位方式打開文件,讀取內容為位元組串,寫入也需要寫入位元組串
- 無論什麼文件都可以使用二進位方式打開,但是二進位文件則不能以文本方式打開,否則後續讀寫會報錯。
1.2.2 讀取文件
- 方法1
xxxxxxxxxx
read([size])
功能: 來直接讀取文件中字元。
參數: 如果沒有給定size參數(默認值為-1)或者size值為負,文件將被讀取直至末尾,給定size最多讀取給定數目個字元(位元組)。
返回值: 返回讀取到的內容
注意:文件過大時候不建議直接讀取到文件結尾,讀到文件結尾會返回空字元串。
- 方法2
xxxxxxxxxx
readline([size])
功能: 用來讀取文件中一行
參數: 如果沒有給定size參數(默認值為-1)或者size值為負,表示讀取一行,給定size表示最多讀取制定的字元(位元組)。
返回值: 返回讀取到的內容
- 方法3
xxxxxxxxxx
readlines([sizeint])
功能: 讀取文件中的每一行作為列表中的一項
參數: 如果沒有給定size參數(默認值為-1)或者size值為負,文件將被讀取直至末尾,給定size表示讀取到size字元所在行為止。
返回值: 返回讀取到的內容列表
- 方法4
xxxxxxxxxx
# 文件對象本身也是一個可迭代對象,在for循環中可以迭代文件的每一行。
for line in f:
print(line)
1.2.3 寫入文件
- 方法1
xxxxxxxxxx
write(data)
功能: 把文本數據或二進位數據塊的字元串寫入到文件中去
參數:要寫入的內容
返回值:寫入的字元個數
注意: 如果需要換行要自己在寫入內容中添加\n
- 方法2
xxxxxxxxxx
writelines(str_list)
功能:接受一個字元串列表作為參數,將它們寫入文件。
參數: 要寫入的內容列表
1.2.4 關閉文件
打開一個文件後我們就可以通過文件對象對文件進行操作了,當操作結束後可以關閉文件操作
- 方法
xxxxxxxxxx
file_object.close()
- 好處
- 可以銷毀對象節省資源,(當然如果不關閉程式結束後對象也會被銷毀)。
- 防止後面對這個對象的誤操作。
1.2.5 with操作
python中的with語句也可以用於訪問文件,在語句塊結束後會自動釋放資源。
- with語句格式
xxxxxxxxxx
with context_expression [as obj]:
with-body
- with訪問文件
xxxxxxxxxx
with open('file','r+') as f:
f.read()
注意 : with語句塊結束後會自動釋放f所以不再需要close().
1.2.6 緩衝區
-
定義
系統自動的在記憶體中為每一個正在使用的文件開闢一個空間,在對文件讀寫時都是先將文件內容載入到緩衝區,再進行讀寫。
-
作用
- 減少和磁碟的交互次數,保護磁碟。
- 提高了對文件的讀寫效率。
-
緩衝區設置
類型 設置方法 注意事項 系統自定義 buffering=-1 行緩衝 buffering=1 當遇到\n時刷新緩衝 指定緩衝區大小 buffering>1 必須以二進位方式打開 -
刷新緩衝區條件
- 緩衝區被寫滿
- 程式執行結束或者文件對象被關閉
- 程式中調用flush()函數
xxxxxxxxxx
file_obj.flush()
1.2.7 文件偏移量
-
定義
打開一個文件進行操作時系統會自動生成一個記錄,記錄每次讀寫操作時所處的文件位置,每次文件的讀寫操作都是從這個位置開始進行的。
注意:
- r或者w方式打開,文件偏移量在文件開始位置
- a方式打開,文件偏移量在文件結尾位置
-
文件偏移量控制
xxxxxxxxxx
31tell()
2功能:獲取文件偏移量大小
3返回值:文件偏移量
xxxxxxxxxx
41seek(offset[,whence])
2功能: 移動文件偏移量位置
3參數:offset 代表相對於某個位置移動的位元組數。負數表示向前移動,正數表示向後移動。
4whence是基準位置的默認值為 0,代表從文件開頭算起,1代表從當前位置算起,2 代表從文件 末尾算起。
注意:必須以二進位方式打開文件時,基準位置才能是1或者2
1.3 os模組
os模組是Python標準庫模組,包含了大量的文件處理函數。
- 獲取文件大小
xxxxxxxxxx
os.path.getsize(file)
功能: 獲取文件大小
參數: 指定文件
返回值: 文件大小
- 查看文件列表
xxxxxxxxxx
os.listdir(dir)
功能: 查看文件列表
參數: 指定目錄
返回值:目錄中的文件名列表
- 查看文件是否存在
xxxxxxxxxx
os.path.exists(file)
功能: 查看文件是否存在
參數: 指定文件
返回值:存在返回True,不存在返回False
- 判斷文件類型
xxxxxxxxxx
os.path.isfile(file)
功能: 判斷文件類型
參數: 指定文件
返回值:普通文件返回True,否則返回False
- 刪除文件
xxxxxxxxxx
os.remove(file)
功能: 刪除文件
參數: 指定文件
2. 正則表達式
2.1 概述
- 學習動機
- 文本數據處理已經成為常見的編程工作之一
- 對文本內容的搜索,定位,提取是邏輯比較複雜的工作
- 為了快速方便的解決上述問題,產生了正則表達式技術
- 定義
即文本的高級匹配模式,其本質是由一系列字元和特殊符號構成的字串,這個字串即正則表達式。
- 原理
通過普通字元和有特定含義的字元,來組成字元串,用以描述一定的字元串規則,比如:重複,位置等,來表達某類特定的字元串,進而匹配。
- 學習目標
- 熟練掌握正則表達式元字元
- 能夠讀懂常用正則表達式,編輯簡單的正則規則
- 能夠熟練使用re模組操作正則表達式
2.2 元字元使用
- 普通字元
匹配規則:每個普通字元匹配其對應的字元
xxxxxxxxxx
e.g.
In : re.findall('ab',"abcdefabcd")
Out: ['ab', 'ab']
注意:正則表達式在python中也可以匹配中文
- 或關係
元字元: |
匹配規則: 匹配 | 兩側任意的正則表達式即可
xxxxxxxxxx
e.g.
In : re.findall('com|cn',"www.baidu.com/www.tmooc.cn")
Out: ['com', 'cn']
- 匹配單個字元
元字元:.
匹配規則:匹配除換行外的任意一個字元
xxxxxxxxxx
e.g.
In : re.findall('張.豐',"張三丰,張四豐,張五豐")
Out: ['張三丰', '張四豐', '張五豐']
- 匹配字符集
元字元: [字符集]
匹配規則: 匹配字符集中的任意一個字元
表達形式:
[abc#!好] 表示 [] 中的任意一個字元 [0-9],[a-z],[A-Z] 表示區間內的任意一個字元 [_#?0-9a-z] 混合書寫,一般區間表達寫在後面
xxxxxxxxxx
e.g.
In : re.findall('[aeiou]',"How are you!")
Out: ['o', 'a', 'e', 'o', 'u']
- 匹配字符集反集
元字元:[^字符集]
匹配規則:匹配除了字符集以外的任意一個字元
xxxxxxxxxx
e.g.
In : re.findall('[^0-9]',"Use 007 port")
Out: ['U', 's', 'e', ' ', ' ', 'p', 'o', 'r', 't']
- 匹配字元串開始位置
元字元: ^
匹配規則:匹配目標字元串的開頭位置
xxxxxxxxxx
e.g.
In : re.findall('^Jame',"Jame,hello")
Out: ['Jame']
- 匹配字元串的結束位置
元字元: $
匹配規則: 匹配目標字元串的結尾位置
xxxxxxxxxx
e.g.
In : re.findall('Jame$',"Hi,Jame")
Out: ['Jame']
規則技巧:
^
和$
必然出現在正則表達式的開頭和結尾處。如果兩者同時出現,則中間的部分必須匹配整個目標字元串的全部內容。
- 匹配字元重複
元字元: *
匹配規則:匹配前面的字元出現0次或多次
xxxxxxxxxx
e.g.
In : re.findall('wo*',"wooooo~~w!")
Out: ['wooooo', 'w']
元字元:+
匹配規則: 匹配前面的字元出現1次或多次
xxxxxxxxxx
e.g.
In : re.findall('[A-Z][a-z]+',"Hello World")
Out: ['Hello', 'World']
元字元:?
匹配規則: 匹配前面的字元出現0次或1次
xxxxxxxxxx
e.g. 匹配整數
In [28]: re.findall('-?[0-9]+',"Jame,age:18, -26")
Out[28]: ['18', '-26']
元字元:{n}
匹配規則: 匹配前面的字元出現n次
xxxxxxxxxx
e.g. 匹配手機號碼
In : re.findall('1[0-9]{10}',"Jame:13886495728")
Out: ['13886495728']
元字元:{m,n}
匹配規則: 匹配前面的字元出現m-n次
xxxxxxxxxx
e.g. 匹配qq號
In : re.findall('[1-9][0-9]{5,10}',"Baron:1259296994")
Out: ['1259296994']
- 匹配任意(非)數字字元
元字元: \d
\D
匹配規則:\d
匹配任意數字字元,\D
匹配任意非數字字元
xxxxxxxxxx
e.g. 匹配埠
In : re.findall('\d{1,5}',"Mysql: 3306, http:80")
Out: ['3306', '80']
- 匹配任意(非)普通字元
元字元: \w
\W
匹配規則: \w
匹配普通字元,\W
匹配非普通字元
說明: 普通字元指數字,字母,下劃線,漢字。
xxxxxxxxxx
e.g.
In : re.findall('\w+',"server_port = 8888")
Out: ['server_port', '8888']
- 匹配任意(非)空字元
元字元: \s
\S
匹配規則:\s
匹配空字元,\S
匹配非空字元
說明:空字元指 空格\r \n \t \v \f
字元
xxxxxxxxxx
e.g.
In : re.findall('\w+\s+\w+',"hello world")
Out: ['hello world']
- 匹配(非)單詞的邊界位置
元字元:\b
\B
匹配規則:\b
表示單詞邊界,\B
表示非單詞邊界
說明:單詞邊界指數字字母(漢字)下劃線與其他字元的交界位置。
xxxxxxxxxx
e.g.
In : re.findall(r'\bis\b',"This is a test.")
Out: ['is']
注意: 當元字元符號與Python字元串中轉義字元衝突的情況則需要使用r將正則表達式字元串聲明為原始字元串,如果不確定那些是Python字元串的轉義字元,則可以在所有正則表達式前加r。
類別 | 元字元 |
---|---|
匹配字元 | . [...] [^...] \d \D \w \W \s \S |
匹配重複 | * + ? {n} {m,n} |
匹配位置 | ^ $ \b \B |
其他 | | () \ |
2.3 匹配規則
2.3.1 特殊字元匹配
-
目的 : 如果匹配的目標字元串中包含正則表達式特殊字元,則在表達式中元字元就想表示其本身含義時就需要進行 \ 處理。
xxxxxxxxxx
11特殊字元: . * + ? ^ $ [] () {} | \
-
操作方法:在正則表達式元字元前加 \ 則元字元就是去其特殊含義,就表示字元本身
xxxxxxxxxx
e.g. 匹配特殊字元 . 時使用 \. 表示本身含義
In : re.findall('-?\d+\.?\d*',"123,-123,1.23,-1.23")
Out: ['123', '-123', '1.23', '-1.23']
2.3.2 貪婪模式和非貪婪模式
- 定義
貪婪模式: 默認情況下,匹配重複的元字元總是儘可能多的向後匹配內容。比如: * + ? {m,n}
非貪婪模式(懶惰模式): 讓匹配重複的元字元儘可能少的向後匹配內容。
- 貪婪模式轉換為非貪婪模式
在對應的匹配重複的元字元後加 ‘?’ 號即可
xxxxxxxxxx
* -> *?
+ -> +?
? -> ??
{m,n} -> {m,n}?
xxxxxxxxxx
e.g.
In : re.findall(r'\(.+?\)',"(abcd)efgh(higk)")
Out: ['(abcd)', '(higk)']
2.3.3 正則表達式分組
- 定義
在正則表達式中,以()建立正則表達式的內部分組,子組是正則表達式的一部分,可以作為內部整體操作對象。
- 作用 : 可以被作為整體操作,改變元字元的操作對象
xxxxxxxxxx
e.g. 改變 +號 重複的對象
In : re.search(r'(ab)+',"ababababab").group()
Out: 'ababababab'
e.g. 改變 |號 操作對象
In : re.search(r'(王|李)\w{1,3}',"王者榮耀").group()
Out: '王者榮耀'
- 捕獲組
捕獲組本質也是一個子組,只不過擁有一個名稱用以表達該子組的意義,這種有名稱的子組即為捕獲組。
格式:
(?P<name>pattern)
xxxxxxxxxx
e.g. 給子組命名為 "pig"
In : re.search(r'(?P<pig>ab)+',"ababababab").group('pig')
Out: 'ab'
- 注意事項
- 一個正則表達式中可以包含多個子組
- 子組可以嵌套但是不宜結構過於複雜
- 子組序列號一般從外到內,從左到右計數
2.3.4 正則表達式匹配原則
- 正確性,能夠正確的匹配出目標字元串.
- 排他性,除了目標字元串之外儘可能少的匹配其他內容.
- 全面性,儘可能考慮到目標字元串的所有情況,不遺漏.
2.4 Python re模組使用
2.4.1 基礎函數使用
xxxxxxxxxx
re.findall(pattern,string,flags = 0)
功能: 根據正則表達式匹配目標字元串內容
參數: pattern 正則表達式
string 目標字元串
flags 功能標誌位,擴展正則表達式的匹配
返回值: 匹配到的內容列表,如果正則表達式有子組則只能獲取到子組對應的內容
xxxxxxxxxx
re.split(pattern,string,max,flags = 0)
功能: 使用正則表達式匹配內容,切割目標字元串
參數: pattern 正則表達式
string 目標字元串
max 最多切割幾部分
flags 功能標誌位,擴展正則表達式的匹配
返回值: 切割後的內容列表
xxxxxxxxxx
re.sub(pattern,replace,string,count,flags = 0)
功能: 使用一個字元串替換正則表達式匹配到的內容
參數: pattern 正則表達式
replace 替換的字元串
string 目標字元串
count 最多替換幾處,默認替換全部
flags 功能標誌位,擴展正則表達式的匹配
返回值: 替換後的字元串
2.4.2 生成match對象
xxxxxxxxxx
re.finditer(pattern,string,flags = 0)
功能: 根據正則表達式匹配目標字元串內容
參數: pattern 正則表達式
string 目標字元串
flags 功能標誌位,擴展正則表達式的匹配
返回值: 匹配結果的迭代器
xxxxxxxxxx
re.match(pattern,string,flags=0)
功能:匹配某個目標字元串開始位置
參數:pattern 正則
string 目標字元串
返回值:匹配內容match object
xxxxxxxxxx
re.search(pattern,string,flags=0)
功能:匹配目標字元串第一個符合內容
參數:pattern 正則
string 目標字元串
返回值:匹配內容match object
2.4.3 match對象使用
-
span() 獲取匹配內容的起止位置
-
groupdict() 獲取捕獲組字典,組名為鍵,對應內容為值
-
group(n = 0)
功能:獲取match對象匹配內容 參數:默認為0表示獲取整個match對象內容,如果是序列號或者組名則表示獲取對應子組內容 返回值:匹配字元串
2.4.4 flags參數擴展
-
作用函數:re模組調用的匹配函數。如:re.findall,re.search….
-
功能:擴展豐富正則表達式的匹配功能
-
常用flag
xxxxxxxxxx
71A == ASCII 元字元只能匹配ascii碼
2
3I == IGNORECASE 匹配忽略字母大小寫
4
5S == DOTALL 使 . 可以匹配換行
6
7M == MULTILINE 使 ^ $可以匹配每一行的開頭結尾位置
注意:同時使用多個flag,可以用豎線連接 flags = re.I | re.A
3. 資料庫
3.1概述
- 數據存儲
-
人工管理階段
缺點 : 數據存儲量有限,共享處理麻煩,操作容易混亂
-
文件管理階段 (.txt .doc .xls)
優點 : 數據可以長期保存,可以存儲大量的數據,使用簡單。
缺點 : 數據一致性差,數據查找修改不方便,數據冗餘度可能比較大。
-
資料庫管理階段
優點 : 數據組織結構化降低了冗餘度,提高了增刪改查的效率,容易擴展,方便程式調用處理
缺點 : 需要使用sql 或者其他特定的語句,相對比較專業
-
資料庫應用領域
資料庫的應用領域幾乎涉及到了需要數據管理的方方面面,融機構、遊戲網站、購物網站、論壇網站 … …都需要資料庫進行數據存儲管理。
- 基本概念
- 資料庫 : 按照數據一定結構,存儲管理數據的倉庫。資料庫是在資料庫管理系統管理和控制下,在一定介質上的數據集合。
- 資料庫管理系統 :管理資料庫的軟體,用於建立和維護資料庫。
- 資料庫系統 : 由資料庫和資料庫管理系統,開發工具等組成的集合 。
-
資料庫分類和常見資料庫
- 關係型資料庫和非關係型資料庫
關係型: 採用關係模型(二維表)來組織數據結構的資料庫
非關係型: 不採用關係模型組織數據結構的資料庫
- 開源和非開源
開源:MySQL、SQLite、MongoDB
非開源:Oracle、DB2、SQL_Server
3.2 MySQL
1996年,MySQL 1.0發布,作者Monty Widenius, 為一個叫TcX的公司打工,當時只是內部發布。到了96年10月,MySQL 3.11.1發布了,一個月後,Linux版本出現了。真正的MySQL關係型資料庫於1998年1月發行第一個版本。MySQL是個開源資料庫,後來瑞典有了專門的MySQL開發公司,將該資料庫發展壯大,在之後被Sun收購,Sun又被Oracle收購。
官網地址://www.mysql.com/
-
MySQL特點
- 是開源資料庫,使用C和C++編寫
- 能夠工作在眾多不同的平台上
- 提供了用於C、C++、Python、Java、Perl、PHP、Ruby眾多語言的API
- 存儲結構優良,運行速度快
- 功能全面豐富
-
MySQL安裝
-
Ubuntu安裝MySQL服務
- 終端執行: sudo apt install mysql-server
- 配置文件:/etc/mysql
- 資料庫存儲目錄 :/var/lib/mysql
-
Windows安裝MySQL
- 下載MySQL安裝包(windows) //dev.mysql.com/downloads/windows/installer/8.0.html
- 直接運行安裝文件安裝
-
-
啟動和連接MySQL服務
-
服務端啟動
- 查看MySQL狀態 : sudo service mysql status
- 啟動/停止/重啟服務:sudo service mysql start/stop/restart
-
連接資料庫
xxxxxxxxxx
11mysql -h 主機地址 -u 用戶名 -p
注意:
- 回車後深入資料庫密碼 (我們設置的是123456)
- 如果鏈接自己主機資料庫可省略 -h 選項
-
關閉連接
xxxxxxxxxx
21ctrl-D
2exit
-
- MySQL資料庫結構
數據元素 –> 記錄 –>數據表 –> 資料庫
-
基本概念解析
- 數據表(table) : 存放數據的表格
- 欄位(column): 每個列,用來表示該列數據的含義
- 記錄(row): 每個行,表示一組完整的數據
3.3 SQL語言
- 什麼是SQL
結構化查詢語言(Structured Query Language),一種特殊目的的程式語言,是一種資料庫查詢和程式設計語言,用於存取數據以及查詢、更新和管理關係資料庫系統。
-
SQL語言特點
- SQL語言基本上獨立於資料庫本身
- 各種不同的資料庫對SQL語言的支援與標準存在著細微的不同
- 每條命令以 ; 結尾
- SQL命令(除了資料庫名和表名)關鍵字和字元串可以不區分字母大小寫
3.4 資料庫管理
- 查看已有庫
show databases;
- 創建庫
create database 庫名 [character set utf8];
xxxxxxxxxx
e.g. 創建stu資料庫,編碼為utf8
create database stu character set utf8;
create database stu charset=utf8;
注意:庫名的命名
- 數字、字母、下劃線,但不能使用純數字
- 庫名區分字母大小寫
- 不要使用特殊字元和mysql關鍵字
- 切換庫
use 庫名;
xxxxxxxxxx
e.g. 使用stu資料庫
use stu;
- 查看當前所在庫
select database();
- 刪除庫
drop database 庫名;
xxxxxxxxxx
e.g. 刪除test資料庫
drop database test;
3.5 數據表管理
-
基本思考過程
- 確定存儲內容
- 明確欄位構成
- 確定欄位數據類型
3.5.1 基礎數據類型
-
數字類型:
- 整數類型:INT,SMALLINT,TINYINT,MEDIUMINT,BIGINT
- 浮點類型:FLOAT,DOUBLE,DECIMAL
- 比特值類型:BIT
注意:
- 對於準確性要求比較高的東西,比如money,用decimal類型減少存儲誤差。聲明語法是DECIMAL(M,D)。M是數字的最大數字位數,D是小數點右側數字的位數。比如 DECIMAL(6,2)最多存6位數字,小數點後佔2位,取值範圍-9999.99到9999.99。
- 比特值類型指0,1值表達2種情況,如真,假
-
字元串類型:
- 普通字元串: CHAR,VARCHAR
- 存儲文本: text
- 存儲二進位數據: BLOB
- 存儲選項型數據:ENUM,SET
注意:
- char:定長,即指定存儲位元組數後,無論實際存儲了多少位元組數據,最終都占指定的位元組大小。默認只能存1位元組數據。存取效率高。
- varchar:不定長,效率偏低 ,但是節省空間,實際佔用空間根據實際存儲數據大小而定。必須要指定存儲大小 varchar(50)
- enum用來存儲給出的多個值中的一個值,即單選,enum(‘A’,’B’,’C’)
- set用來存儲給出的多個值中一個或多個值,即多選,set(‘A’,’B’,’C’)
3.5.2 表的基本操作
- 創建表
create table 表名(欄位名 數據類型 約束,欄位名 數據類型 約束,…欄位名 數據類型 約束);
-
欄位約束
- 如果你想設置數字為無符號則加上 unsigned
- 如果你不想欄位為 NULL 可以設置欄位的屬性為 NOT NULL, 在操作資料庫時如果輸入該欄位的數據為NULL ,就會報錯。
- DEFAULT 表示設置一個欄位的默認值
- AUTO_INCREMENT定義列為自增的屬性,一般用於主鍵,數值會自動加1。
- PRIMARY KEY 關鍵字用於定義列為主鍵。主鍵的值不能重複,且不能為空。
xxxxxxxxxx
e.g. 創建班級表
create table class_1 (id int primary key auto_increment,name varchar(32) not null,age tinyint unsigned not null,sex enum('w','m'),score float default 0.0);
e.g. 創建興趣班表
create table interest (id int primary key auto_increment,name varchar(32) not null,hobby set('sing','dance','draw'),level char not null,price decimal(6,2),remark text);
-
查看數據表
show tables;
-
查看錶結構
desc 表名;
-
查看數據表創建資訊
show create table 表名;
-
刪除表
drop table 表名;
3.6 表數據基本操作
3.5.1 插入(insert)
xxxxxxxxxx
insert into 表名 values(值1),(值2),...;
insert into 表名(欄位1,...) values(值1),...;
xxxxxxxxxx
e.g.
insert into class_1 values (2,'Baron',10,'m',91),(3,'Jame',9,'m',90);
insert into class_1 (name,age,sex,score) values ('Lucy',17,'w',81);
3.6.2 查詢(select)
xxxxxxxxxx
select * from 表名 [where 條件];
select 欄位1,欄位2 from 表名 [where 條件];
xxxxxxxxxx
e.g.
select * from class_1;
select name,age from class_1;
3.6.3 where子句
where子句在sql語句中扮演了重要角色,主要通過一定的運算條件進行數據的篩選,在查詢,刪除,修改中都有使用。
- 算數運算符
xxxxxxxxxx
e.g.
select * from class_1 where age % 2 = 0;
- 比較運算符
xxxxxxxxxx
e.g.
select * from class_1 where age > 8;
select * from class_1 where between 8 and 10;
select * from class_1 where age in (8,9);
- 邏輯運算符
xxxxxxxxxx
e.g.
select * from class_1 where sex='m' and age>9;
3.6.4 更新表記錄(update)
xxxxxxxxxx
update 表名 set 欄位1=值1,欄位2=值2,... where 條件;
注意:update語句後如果不加where條件,所有記錄全部更新
xxxxxxxxxx
e.g.
update class_1 set age=11 where name='Abby';
3.6.5 刪除表記錄(delete)
xxxxxxxxxx
delete from 表名 where 條件;
注意:delete語句後如果不加where條件,所有記錄全部清空
xxxxxxxxxx
e.g.
delete from class_1 where name='Abby';
3.6.6 表欄位的操作(alter)
xxxxxxxxxx
語法 :alter table 表名 執行動作;
* 添加欄位(add)
alter table 表名 add 欄位名 數據類型;
alter table 表名 add 欄位名 數據類型 first;
alter table 表名 add 欄位名 數據類型 after 欄位名;
* 刪除欄位(drop)
alter table 表名 drop 欄位名;
* 修改數據類型(modify)
alter table 表名 modify 欄位名 新數據類型;
* 修改欄位名(change)
alter table 表名 change 舊欄位名 新欄位名 新數據類型;
* 表重命名(rename)
alter table 表名 rename 新表名;
xxxxxxxxxx
e.g.
alter table interest add tel char(11) after name;
3.5.7 時間類型數據
- 日期 : DATE
- 日期時間: DATETIME,TIMESTAMP
- 時間: TIME
- 年份 :YEAR
-
時間格式
xxxxxxxxxx
41date :"YYYY-MM-DD"
2time :"HH:MM:SS"
3datetime :"YYYY-MM-DD HH:MM:SS"
4timestamp :"YYYY-MM-DD HH:MM:SS"
注意:
- datetime :以系統時間存儲
- timestamp :以標準時間存儲但是查看時轉換為系統時區,所以表現形式和datetime相同
xxxxxxxxxx
e.g.
create table marathon (id int primary key auto_increment,athlete varchar(32),birthday date,registration_time datetime,performance time);
-
日期時間函數
- now() 返回伺服器當前日期時間,格式對應datetime類型
- curdate() 返回當前日期,格式對應date類型
- curtime() 返回當前時間,格式對應time類型
-
時間操作
時間類型數據可以進行比較和排序等操作,在寫時間字元串時盡量按照標準格式書寫。
xxxxxxxxxx
select * from marathon where birthday>='2000-01-01';
select * from marathon where birthday>="2000-07-01" and performance<="2:30:00";
3.7 高級查詢語句
-
模糊查詢和正則查詢
-
模糊查詢
LIKE用於在where子句中進行模糊查詢,SQL LIKE 子句中使用百分號
%
來表示任意0個或多個字元,下劃線_
表示任意一個字元。
xxxxxxxxxx
31SELECT field1, field2,...fieldN
2FROM table_name
3WHERE field1 LIKE condition1
xxxxxxxxxx
21e.g.
2mysql> select * from class_1 where name like 'A%';
-
正則查詢
mysql中對正則表達式的支援有限,只支援部分正則元字元:
xxxxxxxxxx
31SELECT field1, field2,...fieldN
2FROM table_name
3WHERE field1 REGEXP condition1
xxxxxxxxxx
21e.g.
2select * from class_1 where name regexp '^B.+';
-
-
as 用法
在sql語句中as用於給欄位或者表重命名
xxxxxxxxxx
21select name as 姓名,age as 年齡 from class_1;
2select * from class_1 as c where c.age > 17;
-
排序
ORDER BY 子句來設定你想按哪個欄位哪種方式來進行排序,再返回搜索結果。
使用 ORDER BY 子句將查詢數據排序後再返回數據:
xxxxxxxxxx
21SELECT field1, field2,...fieldN from table_name1 where field1
2ORDER BY field1 [ASC [DESC]]
默認情況ASC表示升序,DESC表示降序
xxxxxxxxxx
11select * from class_1 where sex='m' order by age desc;
複合排序:對多個欄位排序,即當第一排序項相同時按照第二排序項排序
xxxxxxxxxx
11select * from class_1 order by score desc,age;
-
限制
LIMIT 子句用於限制由 SELECT 語句返回的數據數量 或者 UPDATE,DELETE語句的操作數量
帶有 LIMIT 子句的 SELECT 語句的基本語法如下:
xxxxxxxxxx
41SELECT column1, column2, columnN
2FROM table_name
3WHERE field
4LIMIT [num]
-
聯合查詢
UNION 操作符用於連接兩個以上的 SELECT 語句的結果組合到一個結果集合中。多個 SELECT 語句會刪除重複的數據。
UNION 操作符語法格式:
xxxxxxxxxx
71SELECT expression1, expression2, ... expression_n
2FROM tables
3[WHERE conditions]
4UNION [ALL | DISTINCT]
5SELECT expression1, expression2, ... expression_n
6FROM tables
7[WHERE conditions];
默認UNION後衛 DISTINCT表示刪除結果集中重複的數據。如果使用ALL則返回所有結果集,包含重複數據。
xxxxxxxxxx
select * from class_1 where sex='m' UNION ALL select * from class_1 where age > 9;
-
子查詢
-
定義 : 當一個select語句中包含另一個select 查詢語句,則稱之為有子查詢的語句
-
子查詢出現的位置:
- from 之後 ,此時子查詢的內容作為一個新的表內容,再進行外層select查詢
xxxxxxxxxx
11select name from (select * from class_1 where sex='m') as s where s.score > 90;
注意: 需要將子查詢結果集重命名一下,方便where子句中的引用操作
- where字句中,此時select查詢到的內容作為外層查詢的條件值
xxxxxxxxxx
11select * from class_1 where age = (select age from class_1 where name='Tom');
注意:
- 子句結果作為一個值使用時,返回的結果需要一個明確值,不能是多行或者多列。
- 如果子句結果作為一個集合使用,即where子句中是in操作,則結果可以是一個欄位的多個記錄。
-
-
查詢過程
通過之前的學習看到,一個完整的select語句內容是很豐富的。下面看一下select的執行過程:
xxxxxxxxxx
(5)SELECT DISTINCT <select_list>
(1)FROM <left_table> <join_type> JOIN <right_table> ON <on_predicate>
(2)WHERE <where_predicate>
(3)GROUP BY <group_by_specification>
(4)HAVING <having_predicate>
(6)ORDER BY <order_by_list>
(7)LIMIT <limit_number>
3.8 聚合操作
聚合操作指的是在數據查找基礎上對數據的進一步整理篩選行為,實際上聚合操作也屬於數據的查詢篩選範圍。
3.8.1 聚合函數
方法 | 功能 |
---|---|
avg(欄位名) | 該欄位的平均值 |
max(欄位名) | 該欄位的最大值 |
min(欄位名) | 該欄位的最小值 |
sum(欄位名) | 該欄位所有記錄的和 |
count(欄位名) | 統計該欄位記錄的個數 |
eg1 : 找出表中的最大攻擊力的值?
xxxxxxxxxx
select max(attack) from sanguo;
eg2 : 表中共有多少個英雄?
xxxxxxxxxx
select count(name) as number from sanguo;
eg3 : 蜀國英雄中攻擊值大於200的英雄的數量
xxxxxxxxxx
select count(*) from sanguo where attack > 200;
注意: 此時select 後只能寫聚合函數,無法查找其他欄位。
3.8.2 聚合分組
- group by
給查詢的結果進行分組
e.g. : 計算每個國家的平均攻擊力
xxxxxxxxxx
select country,avg(attack) from sanguo
group by country;
e.g. : 對多個欄位創建索引,此時多個欄位都相同時為一組
xxxxxxxxxx
select age,sex,count(*) from class1 group by age,sex;
e.g. : 所有國家的男英雄中 英雄數量最多的前2名的 國家名稱及英雄數量
xxxxxxxxxx
select country,count(id) as number from sanguo
where gender='M' group by country
order by number DESC
limit 2;
注意: 使用分組時select 後的欄位為group by分組的欄位和聚合函數,不能包含其他內容。group by也可以同時依照多個欄位分組,如group by A,B 此時必須A,B兩個欄位值均相同才算一組。
3.8.3 聚合篩選
- having語句
對分組聚合後的結果進行進一步篩選
xxxxxxxxxx
eg1 : 找出平均攻擊力大於105的國家的前2名,顯示國家名稱和平均攻擊力
select country,avg(attack) from sanguo
group by country
having avg(attack)>105
order by avg(attack) DESC
limit 2;
注意
- having語句必須與group by聯合使用。
- having語句存在彌補了where關鍵字不能與聚合函數聯合使用的不足,where只能操作表中實際存在的欄位。
3.8.4 去重語句
- distinct語句
不顯示欄位重複值
xxxxxxxxxx
eg1 : 表中都有哪些國家
select distinct name,country from sanguo;
eg2 : 計算一共有多少個國家
select count(distinct country) from sanguo;
注意: distinct和from之間所有欄位都相同才會去重
3.8.5 聚合運算
- 查詢表記錄時做數學運算
運算符 : + – * / %
xxxxxxxxxx
eg1: 查詢時顯示攻擊力翻倍
select name,attack*2 from sanguo;
eg2: 更新蜀國所有英雄攻擊力 * 2
update sanguo set attack=attack*2 where country='蜀國';
3.9 索引操作
3.9.1 概述
- 定義
索引是對資料庫表中一列或多列的值進行排序的一種結構,使用索引可快速訪問資料庫表中的特定資訊。
-
優缺點
- 優點 : 加快數據檢索速度,提高查找效率
- 缺點 :佔用資料庫物理存儲空間,當對表中數據更新時,索引需要動態維護,降低數據寫入效率
注意 :
- 通常我們只在經常進行查詢操作的欄位上創建索引
- 對於數據量很少的表或者經常進行寫操作而不是查詢操作的表不適合創建索引
3.9.2 索引分類
- 普通(MUL)
普通索引 :欄位值無約束,KEY標誌為 MUL
- 唯一索引(UNI)
唯一索引(unique) :欄位值不允許重複,但可為 NULL,KEY標誌為 UNI
- 主鍵索引(PRI)
一個表中只能有一個主鍵欄位, 主鍵欄位不允許重複,且不能為NULL,KEY標誌為PRI。通常設置記錄編號欄位id,能唯一鎖定一條記錄
3.9.3 索引創建
- 創建表時直接創建索引
xxxxxxxxxx
create table 表名(
欄位名 數據類型,
欄位名 數據類型,
index 索引名(欄位名),
index 索引名(欄位名),
unique 索引名(欄位名)
);
- 在已有表中創建索引:
xxxxxxxxxx
create [unique] index 索引名 on 表名(欄位名);
xxxxxxxxxx
e.g.
create unique index name_index on cls(name);
- 主鍵索引添加
xxxxxxxxxx
alter table 表名 add primary key(id);
- 查看索引
xxxxxxxxxx
1、desc 表名; --> KEY標誌為:MUL 、UNI。
2、show index from 表名;
- 刪除索引
xxxxxxxxxx
drop index 索引名 on 表名;
alter table 表名 drop primary key; # 刪除主鍵
- 擴展: 藉助性能查看選項去查看索引性能
xxxxxxxxxx
set profiling = 1; 打開功能 (項目上線一般不打開)
show profiles 查看語句執行資訊
3.10 外鍵約束和表關聯關係
3.10.1 外鍵約束
- 約束 : 約束是一種限制,它通過對錶的行或列的數據做出限制,來確保表的數據的完整性、唯一性
- foreign key 功能 : 建立表與表之間的某種約束的關係,由於這種關係的存在,能夠讓表與表之間的數據,更加的完整,關連性更強,為了具體說明創建如下部門表和人員表。
- 示例
xxxxxxxxxx
# 創建部門表
CREATE TABLE dept (id int PRIMARY KEY auto_increment,dname VARCHAR(50) not null);
xxxxxxxxxx
# 創建人員表
CREATE TABLE person (
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(32) NOT NULL,
age tinyint DEFAULT 0,
sex enum('m','w','o') DEFAULT 'o',
salary decimal(8,2) DEFAULT 250.00,
hire_date date NOT NULL,
dept_id int
) ;
上面兩個表中每個人員都應該有指定的部門,但是實際上在沒有約束的情況下人員是可以沒有部門的或者也可以添加一個不存在的部門,這顯然是不合理的。
- 主表和從表:若同一個資料庫中,B表的外鍵與A表的主鍵相對應,則A表為主表,B表為從表。
-
foreign key 外鍵的定義語法:
xxxxxxxxxx
71[CONSTRAINT symbol] FOREIGN KEY(外鍵欄位)
2
3REFERENCES tbl_name (主表主鍵)
4
5[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
6
7[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
該語法可以在 CREATE TABLE 和 ALTER TABLE 時使用
xxxxxxxxxx
101# 創建表時直接簡歷外鍵
2CREATE TABLE person (
3id int PRIMARY KEY AUTO_INCREMENT,
4name varchar(32) NOT NULL,
5age tinyint DEFAULT 0,
6sex enum('m','w','o') DEFAULT 'o',
7salary decimal(10,2) DEFAULT 250.00,
8hire_date date NOT NULL,
9dept_id int ,
10constraint dept_fk foreign key(dept_id) references dept(id));
xxxxxxxxxx
21# 建立表後增加外鍵
2alter table person add constraint dept_fk foreign key(dept_id) references dept(id);
注意:
- 並不是任何情況表關係都需要建立外鍵來約束,如果沒有類似上面的約束關係時也可以不建立。
- 從表的外鍵欄位數據類型與指定的主表主鍵應該相同。
-
通過外鍵名稱解除外鍵約束
xxxxxxxxxx
41alter table person drop foreign key dept_fk;
2
3# 查看外鍵名稱
4show create table person;
注意:刪除外鍵後發現desc查看索引標誌還在,其實外鍵也是一種索引,需要將外鍵名稱的索引刪除之後才可以。
-
級聯動作
-
restrict(默認) : on delete restrict on update restrict
- 當主表刪除記錄時,如果從表中有相關聯記錄則不允許主表刪除
- 當主表更改主鍵欄位值時,如果從表有相關記錄則不允許更改
-
cascade :數據級聯更新 on delete cascade on update cascade
- 當主表刪除記錄或更改被參照欄位的值時,從表會級聯更新
-
set null : on delete set null on update set null
- 當主表刪除記錄時,從表外鍵欄位值變為null
- 當主表更改主鍵欄位值時,從表外鍵欄位值變為null
-
3.10.2 表關聯設計
當我們應對複雜的數據關係的時候,數據表的設計就顯得尤為重要,認識數據之間的依賴關係是更加合理創建數據表關聯性的前提。常見的數據關係如下:
- 一對一關係
一張表的一條記錄一定只能與另外一張表的一條記錄進行對應,反之亦然。
舉例 : 學生資訊和學籍檔案,一個學生對應一個檔案,一個檔案也只屬於一個學生
xxxxxxxxxx
create table student(id int primary key auto_increment,name varchar(50) not null);
create table record(id int primary key auto_increment,
comment text not null,
st_id int unique,
constraint st_fk foreign key(st_id) references student(id)
on delete cascade
on update cascade
);
- 一對多關係
一張表中有一條記錄可以對應另外一張表中的多條記錄;但是反過來,另外一張表的一條記錄 只能對應第一張表的一條記錄,這種關係就是一對多或多對一
舉例: 一個人可以擁有多輛汽車,每輛車登記的車主只有一人。
xxxxxxxxxx
create table person(
id varchar(32) primary key,
name varchar(30),
sex char(1),
age int
);
create table car(
id varchar(32) primary key,
name varchar(30),
price decimal(10,2),
pid varchar(32),
constraint car_fk foreign key(pid) references person(id)
);
- 多對多關係
一對表中(A)的一條記錄能夠對應另外一張表(B)中的多條記錄;同時B表中的一條記錄 也能對應A表中的多條記錄
舉例:一個運動員可以報多個項目,每個項目也會有多個運動員參加,這時為了表達多對多關係需要單獨創建關係表。
xxxxxxxxxx
CREATE TABLE athlete (
id int primary key AUTO_INCREMENT,
name varchar(30),
age tinyint NOT NULL,
country varchar(30) NOT NULL,
description varchar(30)
);
CREATE TABLE item (
id int primary key AUTO_INCREMENT,
rname varchar(30) NOT NULL
);
CREATE TABLE athlete_item (
id int primary key auto_increment,
aid int NOT NULL,
tid int NOT NULL,
CONSTRAINT athlete_fk FOREIGN KEY (aid) REFERENCES athlete (id),
CONSTRAINT item_fk FOREIGN KEY (tid) REFERENCES item (id)
);
3.10.3 E-R模型
- 定義
xxxxxxxxxx
E-R模型(Entry-Relationship)即 實體-關係 數據模型,用於資料庫設計
用簡單的圖(E-R圖)反映了現實世界中存在的事物或數據以及他們之間的關係
- 實體、屬性、關係
實體
xxxxxxxxxx
1、描述客觀事物的概念
2、表示方法 :矩形框
3、示例 :一個人、一本書、一杯咖啡、一個學生
屬性
xxxxxxxxxx
1、實體具有的某種特性
2、表示方法 :橢圓形
3、示例
學生屬性 :學號、姓名、年齡、性別、專業 ...
感受屬性 :悲傷、喜悅、刺激、憤怒 ...
關係
xxxxxxxxxx
1、實體之間的聯繫
2、一對一關聯(1:1)
3、一對多關聯(1:n)
4、多對多關聯(m:n)
- ER圖的繪製
矩形框代表實體,菱形框代表關係,橢圓形代表屬性
3.10.4 表連接
如果多個表存在一定關聯關係,可以多表在一起進行查詢操作,其實表的關聯整理與外鍵約束之間並沒有必然聯繫,但是基於外鍵約束設計的具有關聯性的表往往會更多使用關聯查詢查找數據。
- 簡單多表查詢
多個表數據可以聯合查詢,語法格式如下:
xxxxxxxxxx
select 欄位1,欄位2... from 表1,表2... [where 條件]
xxxxxxxxxx
e.g.
select * from dept,person where dept.id = person.dept_id;
- 內連接
內連接查詢只會查找到符合條件的記錄,其實結果和表關聯查詢是一樣的,官方更推薦使用內連接查詢。
xxxxxxxxxx
SELECT 欄位列表
FROM 表1 INNER JOIN 表2
ON 表1.欄位 = 表2.欄位;
xxxxxxxxxx
select * from person inner join dept on person.dept_id =dept.id;
- 笛卡爾積
笛卡爾積就是將A表的每一條記錄與B表的每一條記錄強行拼在一起。所以,如果A表有n條記錄,B表有m條記錄,笛卡爾積產生的結果就會產生n*m條記錄。
xxxxxxxxxx
select * from person inner join dept;
- 左連接 : 左表為主表,顯示右表中與左表匹配的項
xxxxxxxxxx
SELECT 欄位列表
FROM 表1 LEFT JOIN 表2
ON 表1.欄位 = 表2.欄位;
xxxxxxxxxx
select * from person left join dept on person.dept_id =dept.id;
# 查詢每個部門員工人數
select dname,count(name) from dept left join person on dept.id=person.dept_id group by dname;
- 右連接 :右表為主表,顯示左表中與右表匹配的項
xxxxxxxxxx
SELECT 欄位列表
FROM 表1 RIGHT JOIN 表2
ON 表1.欄位 = 表2.欄位;
xxxxxxxxxx
select * from person right join dept on person.dept_id =dept.id;
注意:我們盡量使用數據量大的表作為基準表,即左表
3.11 視圖
- 視圖概念
視圖是存儲的查詢語句,當調用的時候,產生結果集,視圖充當的是虛擬表的角色。其實視圖可以理解為一個表或多個表中導出來的表,作用和真實表一樣,包含一系列帶有行和列的數據 視圖中,用戶可以使用SELECT語句查詢數據,也可以使用INSERT,UPDATE,DELETE修改記錄,視圖可以使用戶操作方便,並保障資料庫系統安全,如果原表改名或者刪除則視圖也失效。
- 創建視圖
xxxxxxxxxx
語法結構:
CREATE [OR REPLACE] VIEW [view_name] AS [SELECT_STATEMENT];
釋義:
CREATE VIEW: 創建視圖
OR REPLACE : 可選,如果添加原來有同名視圖的情況下會覆蓋掉原有視圖
view_name : 視圖名稱
SELECT_STATEMENT :SELECT語句
e.g.
create view c1 as select name,age from class_1;
-
視圖表的增刪改查操作
視圖的增刪改查操作與一般表的操作相同,使用insert update delete select即可,但是原數據表的約束條件仍然對視圖產生作用。
-
查看現有視圖
xxxxxxxxxx
11show full tables in stu where table_type like 'VIEW';
-
刪除視圖
drop view [IF EXISTS] 視圖名;
IF EXISTS 表示如果存在,這樣即使沒有指定視圖也不會報錯。
xxxxxxxxxx
11drop view if exists c1;
-
修改視圖
參考創建視圖,將create關鍵字改為alter
xxxxxxxxxx
11alter view c1 as select name,age,score from class_1;
-
視圖作用
- 作用
-
是對數據的一種重構,不影響原數據表的使用。
-
簡化高頻複雜操作的過程,就像一種對複雜操作的封裝。
-
提高安全性,可以給不同用戶提供不同的視圖。
-
讓數據更加清晰。
- 缺點
-
視圖的性能相對較差,從資料庫視圖查詢數據可能會很慢。
3.12 函數和存儲過程
存儲過程和函數是事先經過編譯並存儲在資料庫中的一段sql語句集合,調用存儲過程和函數可以簡化應用開發工作,提高數據處理的效率。
3.12.1 函數創建
xxxxxxxxxx
delimiter 自定義符號 -- 如果函數體只有一條語句, begin和end可以省略, 同時delimiter也可以省略
create function 函數名(形參列表) returns 返回類型 -- 注意是retruns
begin
函數體 -- 函數語句集,set @a 定義變數
return val
end 自定義符號
delimiter ;
釋義:
delimiter 自定義符號 是為了在函數內些語句方便,制定除了;之外的符號作為函數書寫結束標誌,一般用$$或者//
形參列表 : 形參名 類型 類型為mysql支援類型
返回類型: 函數返回的數據類型,mysql支援類型即可
函數體: 若干sql語句組成,如果只有一條語句也可以不寫delimiter和begin,end
return: 返回指定類型返回值
xxxxxxxxxx
e.g. 無參數的函數調用
delimiter $$
create function st() returns int
begin
return (select score from class_1 order by score desc limit 1);
end $$
delimiter ;
select st();
xxxxxxxxxx
e.g. 含有參數的函數調用
delimiter $$
create function queryNameById(uid int(10))
returns varchar(20)
begin
return (select name from class_1 where id=uid);
end $$
delimiter ;
select queryNameById(1);
-
設置變數
- 用戶變數方法: set @[變數名] = 值;使用時用@[變數名]。
- 局部變數 : 在函數內部設置 declare [變數名] [變數類型] ;局部變數可以使用set賦值或者使用into關鍵字。
3.12.2存儲過程創建
創建存儲過程語法與創建函數基本相同,但是沒有返回值。
xxxxxxxxxx
delimiter 自定義符號
create procedure 存儲過程名(形參列表)
begin
存儲過程 -- 存儲過程語句集,set @a 定義變數
end 自定義符號
delimiter ;
釋義:
delimiter 自定義符號 是為了在函數內些語句方便,制定除了;之外的符號作為函數書寫結束標誌
形參列表 :[ IN | OUT | INOUT ] 形參名 類型
in 輸入,out 輸出,inout 可以輸入也可以輸出
存儲過程: 若干sql語句組成,如果只有一條語句也可以不寫delimiter和begin,end
xxxxxxxxxx
e.g. 存儲過程創建和調用
delimiter $$
create procedure st()
begin
select name,age from class_1;
select name,score from class_1 order by score desc;
end $$
delimiter ;
call st();
-
存儲過程三個參數的區別
-
IN 類型參數可以接收變數也可以接收常量,傳入的參數在存儲過程內部使用即可,但是在存儲過程內部的修改無法傳遞到外部。
-
OUT 類型參數只能接收一個變數,接收的變數不能夠在存儲過程內部使用(內部為NULL),但是可以在存儲過程內對這個變數進行修改。因為定義的變數是全局的,所以外部可以獲取這個修改後的值。
-
INOUT類型參數同樣只能接收一個變數,但是這個變數可以在存儲過程內部使用。在存儲過程內部的修改也會傳遞到外部。
-
xxxxxxxxxx
e.g. : 分別將參數類型改為IN OUT INOUT 看一下結果區別
delimiter $$
create procedure p_out ( OUT num int )
begin
select num;
set num=100;
select num;
end $$
delimiter ;
set @num=10;
call p_out(@num)
3.12.3 存儲過程和存儲函數操作
- 調用存儲過程
語法:
xxxxxxxxxx
call 存儲過程名字([存儲過程的參數[,……]])
- 調用存儲函數
語法:
xxxxxxxxxx
select 存儲函數名字([存儲過程的參數[,……]])
- 使用show status語句查看存儲過程和函數的資訊
語法:
xxxxxxxxxx
show {procedure|function} status [like』存儲過程或存儲函數的名稱』]
顯示內容:資料庫、名字、類型、創建者、創建和修改日期
- 使用show create語句查看存儲過程和函數的定義
語法:
xxxxxxxxxx
show create {procedure|function} 存儲過程或存儲函數的名稱
-
查看所有函數或者存儲過程
xxxxxxxxxx
11select name from mysql.proc where db='stu' and type='[procedure/function]';
-
刪除存儲過程或存儲函數
語法:
xxxxxxxxxx
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
3.12.4 函數和存儲過程區別
- 函數有且只有一個返回值,而存儲過程不能有返回值。
- 函數只能有輸入參數,而存儲過程可以有in,out,inout多個類型參數。
- 存儲過程中的語句功能更豐富,實現更複雜的業務邏輯,可以理解為一個按照預定步驟調用的執行過程,而函數中不能展示查詢結果集語句,只是完成查詢的工作後返回一個結果,功能針對性比較強。
- 存儲過程一般是作為一個獨立的部分來執行(call調用)。而函數可以作為查詢語句的一個部分來調用。
3.13 事務控制
3.13.1 事務概述
MySQL 事務主要用於處理操作量大,複雜度高的數據。比如說,在人員管理系統中,你刪除一個人員,既需要刪除人員的基本資料,也要刪除和該人員相關的資訊,如信箱,文章等等,如果操作就必須同時操作成功,如果有一個不成功則所有數據都不動。這時候資料庫操作語句就構成一個事務。事務主要處理數據的增刪改操作。
- 定義
一件事從開始發生到結束的過程
- 作用
確保數據操作過程中的安全。
3.13.2 事務操作
- 開啟事務
xxxxxxxxxx
mysql>begin; # 方法1
- 開始執行事務中的若干條SQL命令(增刪改)
- 終止事務,若begin之後使用commit提交事務或者使用rollback進行事務回滾。
xxxxxxxxxx
mysql>commit; # 事務中SQL命令都執行成功,提交到資料庫,結束!
mysql>rollback; # 有SQL命令執行失敗,回滾到初始狀態,結束!
3.13.3 事務四大特性
- 原子性(atomicity)
一個事務必須視為一個不可分割的最小工作單元,對於一個事務來說,不可能只執行其中的一部分操作,整個事務中的所有操作要麼全部提交成功,要麼全部失敗回滾
- 一致性(consistency)
事務完成時,數據必須處於一致狀態,數據的完整性約束沒有被破壞。
- 隔離性(isolation)
資料庫允許多個並發事務同時對其數據進行讀寫和修改的能力,而多個事務相互獨立。隔離性可以防止多個事務並發執行時由於交叉執行而導致數據的不一致。
- 持久性(durability)
一旦事務提交,則其所做的修改就會永久保存到資料庫中。此時即使系統崩潰,修改的數據也不會丟失。
3.13.4 事務隔離級別
事務四大特性中的隔離性是在使用事務時最為需要注意的特性,因為隔離級別不同帶來的操作現象也有區別
-
隔離級別
-
讀未提交:read uncommitted
事物A和事物B,事物A未提交的數據,事物B可以讀取到 這裡讀取到的數據叫做「臟數據」 這種隔離級別最低,這種級別一般是在理論上存在,資料庫隔離級別一般都高於該級別
-
讀已提交:read committed
事物A和事物B,事物A提交的數據,事物B才能讀取到 這種隔離級別高於讀未提交 換句話說,對方事物提交之後的數據,我當前事物才能讀取到 這種級別可以避免「臟數據」 這種隔離級別會導致「不可重複讀取」
-
可重複讀:repeatable read
事務A和事務B,事務A提交之後的數據,事務B讀取不到 事務B是可重複讀取數據 這種隔離級別高於讀已提交 MySQL默認級別 雖然可以達到可重複讀取,但是會導致「幻像讀」
-
串列化:serializable
事務A和事務B,事務A在操作資料庫時,事務B只能排隊等待 這種隔離級別很少使用,吞吐量太低,用戶體驗差 這種級別可以避免「幻像讀」,每一次讀取的都是資料庫中真實存在數據,事務A與事務B串列,而不並發
-
3.14 資料庫優化
3.14.1 資料庫設計範式
設計關係資料庫時,遵從不同的規範要求,設計出合理的關係型資料庫,這些不同的規範要求被稱為不同的範式。
目前關係資料庫有六種範式:第一範式(1NF)、第二範式(2NF)、第三範式(3NF)、巴斯-科德範式(BCNF)、第四範式(4NF)和第五範式(5NF,又稱完美範式)。
各種範式呈遞次規範,越高的範式資料庫冗餘越小。但是範式越高也意味著表的劃分更細,一個資料庫中需要的表也就越多,此時多個表聯接在一起的花費是巨大的,尤其是當需要連接的兩張或者多張表數據非常龐大的時候,表連接操作幾乎是一個噩夢,這嚴重地降低了系統運行性能。所以通常資料庫設計遵循第一第二第三範式,以避免數據操作異常,又不至於表關係過於複雜。
範式簡介:
-
第一範式: 資料庫表的每一列都是不可分割的原子數據項,而不能是集合,數組,記錄等組合的數據項。簡單來說要求資料庫中的表示二維表,每個數據元素不可再分。
例如: 在中國的話通常理解都是姓名是一個不可再拆分的單位,這時候就符合第一範式;但是在國外的話還要分為FIRST NAME和LAST NAME,這時候姓名這個欄位就是還可以拆分為更小的單位的欄位,就不符合第一範式了。
-
第二範式: 第二範式(2NF)要求資料庫表中的每個實例或記錄必須可以被唯一地區分,所有屬性依賴於主屬性。即選取一個能區分每個實體的屬性或屬性組,作為實體的唯一標識,每個屬性都能被主屬性篩選。其實簡單理解要設置一個區分各個記錄的主鍵就好了。
-
第三範式: 在第二範式的基礎上屬性不傳遞依賴,即每個屬性不依賴其他非主屬性。要求一個表中不包含已在其它表中包含的非主關鍵字資訊。其實簡單來說就是合理使用外鍵,使不同的表中不要有重複的欄位就好了。
3.14.2 MySQL存儲引擎
- 定義: mysql資料庫管理系統中用來處理表的處理器
- 基本操作
xxxxxxxxxx
1、查看所有存儲引擎
mysql> show engines;
2、查看已有表的存儲引擎
mysql> show create table 表名;
3、創建表指定
create table 表名(...)engine=MyISAM;
4、已有表指定
alter table 表名 engine=InnoDB;
-
常用存儲引擎特點
InnoDB
xxxxxxxxxx
511. 支援行級鎖,僅對指定的記錄進行加鎖,這樣其它進程還是可以對同一個表中的其它記錄進行操作。
22. 支援外鍵、事務、事務回滾
33. 表欄位和索引同存儲在一個文件中
41. 表名.frm :表結構
52. 表名.ibd : 表記錄及索引文件
MyISAM
xxxxxxxxxx
511. 支援表級鎖,在鎖定期間,其它進程無法對該表進行寫操作。如果你是寫鎖,則其它進程則讀也不允許
22. 表欄位和索引分開存儲
31. 表名.frm :表結構
42. 表名.MYI : 索引文件(my index)
53. 表名.MYD : 表記錄(my data)
-
如何選擇存儲引擎
xxxxxxxxxx
911. 執行查操作多的表用 MyISAM(使用InnoDB浪費資源)
22. 執行寫操作多的表用 InnoDB
3
4CREATE TABLE tb_stu(
5id int(11) NOT NULL AUTO_INCREMENT,
6name varchar(30) DEFAULT NULL,
7sex varchar(2) DEFAULT NULL,
8PRIMARY KEY (id)
9)ENGINE=MyISAM;
3.14.3 欄位數據類型選擇
- 優先程度 數字 > 時間日期 > 字元串
- 同一級別 佔用空間小的 > 佔用空間多的
xxxxxxxxxx
字元串在查詢比較排序時數據處理慢
佔用空間少,資料庫占磁碟頁少,讀寫處理就更快
- 對數據存儲精確不要求 float > decimel
- 如果很少被查詢可以用 TIMESTAMP(時間戳實際是整形存儲)
3.14.4 鍵的設置
- Innodb如果不設置主鍵也會自己設置隱含的主鍵,所以最好自己設置
- 盡量設置佔用空間小的欄位為主鍵
- 外鍵的設置用於保持數據完整性,但是會降低數據導入和操作效率,特別是高並發情況下,而且會增加維護成本
- 雖然高並發下不建議使用外鍵約束,但是在表關聯時建議在關聯鍵上建立索引,以提高查找速度
3.14.5 explain語句
使用 EXPLAIN 關鍵字可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。這可以幫你分析你的查詢語句或是表結構的性能瓶頸。通過explain命令可以得到:
- 表的讀取順序
- 數據讀取操作的操作類型
- 哪些索引可以使用
- 哪些索引被實際使用
- 表之間的引用
- 每張表有多少行被優化器查詢
xxxxxxxxxx
explain select * from class_1 where id <5;
EXPLAIN主要欄位解析:
- table:顯示這一行的數據是關於哪張表的
- type:這是最重要的欄位之一,顯示查詢使用了何種類型。從最好到最差的連接類型為system、const、eq_reg、ref、range、index和ALL,一般來說,得保證查詢至少達到range級別,最好能達到ref。
xxxxxxxxxx
type中包含的值:
- system、const: 可以將查詢的變數轉為常量. 如id=1; id為 主鍵或唯一鍵.
- eq_ref: 訪問索引,返回某單一行的數據.(通常在聯接時出現,查詢使用的索引為主鍵或唯一鍵)
- ref: 訪問索引,返回某個值的數據.(可以返回多行) 通常使用=時發生
- range: 這個連接類型使用索引返回一個範圍中的行,比如使用>或<查找東西,並且該欄位上建有索引時發生的情況
- index: 以索引的順序進行全表掃描,優點是不用排序,缺點是還要全表掃描
- ALL: 全表掃描,應該盡量避免
- possible_keys:顯示可能應用在這張表中的索引。如果為空,表示沒有可能應用的索引。
- key:實際使用的索引。如果為NULL,則沒有使用索引。
- key_len:使用的索引的長度。在不損失精確性的情況下,長度越短越好
- rows:MySQL認為必須檢索的用來返回請求數據的行數
3.14.6 SQL優化
-
盡量選擇數據類型占空間少,在where ,group by,order by中出現的頻率高的欄位建立索引
-
盡量避免使用 select * …;用具體欄位代替 * ,不要返回用不到的任何欄位
-
少使用like %查詢,否則會全表掃描
-
控制使用自定義函數
-
單條查詢最後添加 LIMIT 1,停止全表掃描
-
where子句中不使用 != ,否則放棄索引全表掃描
-
盡量避免 NULL 值判斷,否則放棄索引全表掃描
優化前:select number from t1 where number is null;
優化後:select number from t1 where number=0;
- 在number列上設置默認值0,確保number列無NULL值
-
盡量避免 or 連接條件,否則會放棄索引進行全表掃描,可以用union代替
優化前:select id from t1 where id=10 or id=20;
優化後: select id from t1 where id=10 union all select id from t1 where id=20;
-
盡量避免使用 in 和 not in,否則會全表掃描
優化前:select id from t1 where id in(1,2,3,4);
優化後:select id from t1 where id between 1 and 4;
3.14.7 表的拆分
垂直拆分 : 表中列太多,分為多個表,每個表是其中的幾個列。將常查詢的放到一起,blob或者text類型欄位放到另一個表
水平拆分 : 減少每個表的數據量,通過關鍵字進行劃分然後拆成多個表
3.15 資料庫備份和用戶管理
3.15.1 表的複製
- 表能根據實際需求複製數據
- 複製表時不會把KEY屬性複製過來
語法
xxxxxxxxxx
create table 表名 select 查詢命令;
3.15.2 數據備份
- 備份命令格式
mysqldump -u 用戶名 -p 源庫名 > ~/stu.sql
- 恢復命令格式
mysql -u root -p 目標庫名 < stu.sql
3.15.3 用戶許可權管理
開啟MySQL遠程連接
xxxxxxxxxx
更改配置文件,重啟服務!
1.cd /etc/mysql/mysql.conf.d
2.sudo vi mysqld.cnf 找到43行左右,加 # 注釋
# bind-address = 127.0.0.1
3.保存退出
4.sudo service mysql restart
5.進入mysql修改用戶表host值
use mysql;
update user set host='%' where user='root';
6.刷新許可權
flush privileges;
添加授權用戶
xxxxxxxxxx
1. 用root用戶登錄mysql
mysql -u root -p
2. 添加用戶 % 表示自動選擇可用IP
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
3. 許可權管理
# 增加許可權
grant 許可權列表 on 庫.表 to "用戶名"@"%" identified by "密碼" with grant option;
# 刪除許可權
revoke insert,update,select on 庫.表 from 'user'@'%';
4. 刷新許可權
flush privileges;
5. 刪除用戶
drop user "用戶名"@"%"
許可權列表
xxxxxxxxxx
all privileges 、select 、insert ,update,delete,alter等。
庫.表 : *.* 代表所有庫的所有表
示例
xxxxxxxxxx
1. 創建用戶
mysql>create user 'work'@'%' identified by '123';
2. 添加授權用戶work,密碼123,對所有庫的所有表有所有許可權
mysql>grant all privileges on *.* to 'work'@'%' identified by '123' with grant option;
mysql>flush privileges;
3. 添加用戶duty,密碼123,對books庫中所有表有查看,插入許可權
mysql>grant select,insert on books.* to 'duty'@'%' identified by '123' with grant option;
mysql>flush privileges;
4. 刪除work用戶的刪除許可權
mysql>revoke delete on *.* from "work"@"%";
5. 刪除用戶duty
drop user "duty"@"%";
3.16 pymysql模組
pymysql是一個第三方庫,如果自己的電腦上沒有可以在終端使用命令進行安裝。
xxxxxxxxxx
sudo pip3 install pymysql
- pymysql使用流程
- 建立資料庫連接(db = pymysql.connect(…))
- 創建游標對象(cur = db.cursor())
- 游標方法: cur.execute(“insert ….”)
- 提交到資料庫或者獲取數據 : db.commit()/cur.fetchall()
- 關閉游標對象 :cur.close()
- 斷開資料庫連接 :db.close()
- 常用函數
xxxxxxxxxx
db = pymysql.connect(參數列表)
功能: 鏈接資料庫
host :主機地址,本地 localhost
port :埠號,默認3306
user :用戶名
password :密碼
database :庫
charset :編碼方式,推薦使用 utf8
xxxxxxxxxx
cur = db.cursor()
功能: 創建游標
返回值:返回遊標對象,用於執行具體SQL命令
xxxxxxxxxx
cur.execute(sql,list_)
功能: 執行SQL命令
參數: sql sql語句
list_ 列表,用於給sql語句傳遞參量
cur.executemany(sql命令,list_)
功能: 多次執行SQL命令,執行次數由列表中元組數量決定
參數: sql sql語句
list_ 列表中包含元組 每個元組用於給sql語句傳遞參量,一般用於寫操作。
xxxxxxxxxx
cur.fetchone() 獲取查詢結果集的第一條數據,查找到返回一個元組否則返回None
cur.fetchmany(n) 獲取前n條查找到的記錄,返回結果為元組嵌套元組, ((記錄1),(記錄2)),查詢不到內容返回空元組。
cur.fetchall() 獲取所有查找到的記錄,返回結果形式同上。
cur.close() 關閉游標對象
xxxxxxxxxx
db.commit() 提交到資料庫執行
db.rollback() 回滾,用於當commit()出錯是回復到原來的數據形態
db.close() 關閉連接
-
文件存儲
-
存儲文件路徑
- 優點:節省資料庫空間,提取方便
- 缺點:文件或者資料庫發生遷移會導致文件丟失
-
存儲文件本身
- 優點:安全可靠,資料庫在文件就在
- 缺點:佔用資料庫空間大,文件存取效率低
-