135 python|第七部分:資料庫(二)

語言: CN / TW / HK

點選關注 「緩緩而行」, 讓我們一起探索 python 學習之路~

前言:本篇 文章是資料庫部分的最後一篇文章:

目錄如下:

01 檢視

1.1 概念

1.2 檢視操作

02 函式和儲存過程

2.1 函式和儲存過程建立

2.2 儲存過程和儲存函式操作

2.3 函式和儲存過程區別

03 事務控制

3.1 事務概述

3.2 事務操作

3.3 事務四大特性

3.4 事務隔離級別

04 資料庫優化

4.1 資料庫設計正規化

4.2 MySQL儲存引擎

4.3 欄位資料型別和鍵的選擇

4.4 explain語句

4.5 SQL優化

4.6 表的拆分

05 資料庫安全和管理

5.1 表的複製

5.2 資料庫備份

5.3 MySQL遠端連線

5.4 新增使用者和授權

06 pymysql模組

6.1 pycharm新建專案

6.2 pymysql使用流程

6.3 常用函式

引 言

134  python|第七部分:資料庫(一) 上篇文章是python資料庫中常用的知識點,本篇文章每一個小節的內容可以幫助我們解決資料庫開發過程中的特定問題,使用頻率沒有那麼頻繁。

01 檢視

        

1.1 概念

  

檢視是儲存的查詢語句,可以理解為一個虛擬的映象表。 如果原表改名或者刪除,檢視也會失效。

為什麼要建立檢視呢?

首先 出於高效的角度來講 ,資料使用者(比如技術部、銷售部、大客戶經理等)擁有的資料並非越多越好。比如技術部需要用到所有的資料,銷售部可能只需要獲得普通vip的資料資訊,大客戶經理只需要svip的資料資訊。

其次, 從資料安全性的角度來講 ,資料並不能對每個人都開放同樣的許可權,以免資訊洩露。

當然,檢視除了以上優點外,在效能上相對較差,從資料庫檢視查詢資料會比較慢。

1.2 檢視操作

檢視操作
功能 語法
建立檢視 CREATE [OR REPLACE] VIEW [view_name] AS [SELECT_STATEMENT];
OR REPLACE 可選,若新新增檢視和原有檢視同名,會覆蓋掉原有檢視。
視圖表的增刪改查 與一般表操作相同,使用INSERT、UPDATE、DELETE、SELECT
原資料表的約束條件對檢視仍起作用

檢視現有檢視

show full tables in 庫名;
刪除檢視 drop view [if exists] 檢視名;
加上if exists ,沒有該檢視名也不會報錯。if exists 在刪表、刪庫時也可以使用
修改 檢視 alter [OR REPLACE] VIEW [view_name] AS [SELECT_STATEMENT];

例項1.建立並檢視現有檢視

以下對視圖表的增刪改查和一般表的操作相同

例項2.查看錶資料

例項3.插入表資料

例項4.更新表資料

例項5.刪除表資料

例項6.新建多表檢視

多表檢視以查為主,如果進行寫操作,一條寫語句不能同時影響多張表。

如下圖,class表和hobby表是通過name建立聯絡的,刪除name會報錯,而對年齡進行寫操作則沒問題。

例項7.刪除檢視

例項8.修改檢視

02 函式和儲存過程

2.1 函式和儲存過程建立

函式&儲存過程建立
型別 語法
函式建立 delimiter 自定義符號
create function 函式名(形參列表)returns 返回型別
begin
函式體
return val;
end 自定義符號
delimiter ;

1. 自定義符號 可以指定除了;之外的符號作為函式書寫結束標誌,一般用 $$或者//

2. 形參列表: 形參名 型別

3. 返回型別 :函式返回的資料型別

4. 函式體 :若干sql語句組成(可以不用縮排)

5. return :返回指定型別返回值

設定變數:

函式體不能直接寫select語句

,如果想要查內容,可以賦值給變數。

1.定義 使用者變數 set @[變數名]=值 ; 使用時@[變數名]

2.定義 區域性變數 :在函式內部設定  declare [變數名][變數型別];

區域性變數可以使用 set賦值 或者使用 into關鍵字

(兩種方式都可以)

在函式體內定義區域性變數,語法格式為:

declare 變數名1 型別;

declare 變數名2 型別;

set 變數名1=(select語句);

select語句 into 變數名2;

return 變數;

注:儲存過程設定變數的方式和函式一樣

儲存過程建立 delimiter 自定義符號
create procedure 儲存過程名(形參列表)
begin
儲存過程
end 自定義符號
delimiter ;

1. 形參列表 :[IN | OUT | INOUT] 形參名 型別

in:輸入 out:輸出 inout:既可以輸入也可以輸出

2. 儲存過程 :若干sql語句組成,如果只有一條sql語句,也可以不寫delimiter和begin、end

IN :可以接收變數,也可以接收常量,傳入的引數 在儲存過程內部使用 ,儲存過程內部的修改 無法傳遞到外部
OUT :只能接收變數,接收的變數不 能在儲存過程內部使用 (內部為NULL),但是可以在儲存過程內對該變數修改。定義的變數叫使用者變數,類似python中的全域性變數,外部可以獲取修改後的值。
I NOUT :只能接收變數,該變數 可以在儲存過程內部使用內部修改可以傳遞到外部

1.函式例項

例項1.建立函式舉例

例項2.函式使用

1.放在select 後展示結果

2.放在where子句或其他位置作為值提供者(要求函式執行過程中 不能有寫操作)

有寫操作會報錯

沒有寫操作可以查詢

例項3. 函式體內定義區域性變數

例項4.函式傳參

2.儲存過程例項

例項1.儲存過程的建立和呼叫

和函式不同,儲存過程的函式體可以進行寫操作和查操作。函式有返回值,儲存過程沒有返回值,它的主要作用是通過呼叫儲存過程檢視對其進行操作後的結果。

例項2.儲存過程傳參

(1)IN型別(用得更多)

建立儲存過程,傳入IN型別形參,設定使用者變數

呼叫儲存過程,並傳入變數型別的引數a(IN型別也可以傳入常量引數)

儲存過程內部的修改無法傳遞到外部,a的值和修改前相同

(2)OUT型別

建立儲存過程,傳入OUT型別形參,設定使用者變數

儲存過程內部無法使用變數a,但可以修改

外部可以獲取修改後的值

(3)INOUT型別

兼具IN和OUT兩種型別的特點,此處省略具體步驟

2.2 儲存過程和儲存函式操作

                  

儲存過程&儲存函式操作
功能 語法
呼叫儲存過程 call  儲存過程名([儲存過程的引數[,......]]);
呼叫儲存函式 select  儲存函式名([函式的引數[,......]]);
檢視儲存過程和儲存函式的定義 show create {procedure|function} 儲存過程名或儲存函式名;
檢視所有 儲存過程和儲存函式

select 欄位1,欄位2... from mysql.proc where db='資料庫名' ;

show procedure|function status where db="資料庫名";

注:第一條語句僅可以用在5.7及之前的版本;

第二條語句可以在5.7及8.0版本中使用

刪除儲存過程或儲存函式 drop {procedure|function}  [if exists] sp_name;

例項1.檢視儲存過程定義

show create procedure proc_out;(用的較少)

檢視函式略

例項2. 檢視所有儲存過程

show procedure|function status where db="stu";

檢視所有函式略

例項3. 刪除儲存過程

刪除函式略

2.3 函式和儲存過程區別

1.函式 有且只有一個返回值 ,儲存過程 不能有返回值

2.函式只能有 普通引數 ,而儲存過程可以有 in,out,inout多個型別引數

3.函式 不能展示查詢結果集語句,只能在完成查詢後返回一個結果 ,功能針對性比較強;而儲存過程中的語句功能更豐富,可以實現更復雜的業務邏輯,可以理解為 一個按預定步驟呼叫的執行過程

4.函式可以 作為查詢語句的一個部分來呼叫 ;而儲存過程一般是 作為一個獨立的部分來執行 (call呼叫)。

注:實際工作中,儲存過程用的更多,因為自定義函式效率比較低。

03 事務控制

3.1 事務概述

定義:一件事從開始發生到結束的過程。

作用:確保資料操作過程中的資料完整和使用安全(多人使用,互不干擾)。

事務控制的主要是寫操作。

3.2 事務操作

事務操作
功能 語法
開啟事務 begin;
執行事務中的若干條sql命令
終止事務

commit ;

事務中sql命令都執行成功,提交到資料庫,結束

rollback;

有sql命令執行失敗,回滾到初始狀態,結束

注: 事務操作只針對資料操作,rollback不能恢復資料庫、資料表結構操作。

例項1

1.開啟事務

2.執行sql命令

操作1

操作2

操作3

3.通過事務回滾終止事務

回滾到初始狀態

也可以通過commit終止事務,就無法回到原來的狀態了。

例項2 

情況1.兩個終端均不開啟事務

開啟兩個終端,在第一個終端中對class表進行操作,在第二個終端中檢視,會發現class表會 同步更改

終端1

終端2

情況2. 1個終端開啟事務

如果在進行上述操作前 開啟事務 ,終端1 class表的變化 不會影響 到終端2

終端1

終端2

終端1 開啟事務時,其他終端是無法對終端1操作的表進行操作的 。如下圖,在操作終端2時會顯示被阻塞。過了1分鐘左右會報“ 鎖等待超時 ”的錯誤。

直到終端1終止事務,終端2才可以對該表進行操作

終端1

終端2

情況3.兩個終端都開啟事務

對終端1的class表進行操作,終端2中的class表並不會顯示操作後的變化,反之也一樣,這表示出了事務的隔離性(在下文介紹)。同時,在終端2中無法對被終端1操作的記錄進行寫操作(比如Elsa所在的記錄),但可以對其他記錄進行寫操作

即使終端1結束事務,在終端2中檢視class表時,顯示的也只是當前終端操作的結果,對終端1的操作不予體現。除非終端2的事務也結束了,再進行查詢時,才能看到終端1的操作結果。

終端1

終端2

3.3 事務四大特性

事務四大特性 ACID
特性 說明

原子性 

atomicity

一個事務就是一個不可分割的最小工作單元 ,對於一個事務來說,不可能只執行其中一部分操作,整個事務中的所有操作 要麼全部提交成功 要麼全部失敗回滾

一致性 

consistency

事務完成時,資料必須處於一致狀態,資料的完整性約束沒有被破壞。

隔離性 

isolation

資料庫允許多個併發事務同時對資料進行讀寫和修改的能力,而 多個事務互相獨立 。隔離性可以防止多個事務併發執行時由於交叉執行而導致資料的不一致。

永續性 

durability

一旦事務提交,則其所做的修改就會永久儲存到資料庫中。 即使此係統崩潰,修改的資料也不會丟失。

3.4 事務隔離級別

4

事務四大特性中的 隔離性 是在使用事務時最需要注意的特性,隔離級別不同,帶來的操作現象也不同。

事務隔離級別
級別 說明

讀未提交 

read uncommitted

事務B可以立即讀取到事務A 還沒有提交 的資料 ,這裡讀取到的資料叫‘’‘ 髒資料 ’(虛假的資料,因為A對資料的操作還在繼續)。這種隔離級別最低,一般是在理論中存在。(很少使用)

讀已提交 

read committed

rc級別 事務B可以讀取到事務A 已經提交 的資料。 可以避免“髒資料”的出現。但會導致 不可重複讀取 ,即假如事務B沒有進行任何操作,但資料發生了更改,無法再看到更改前的資料,這個過程是不可逆的。

可重複讀 

repeatable read

rr級別 事務A提交後的資料,事務B 讀取不到 MySQL預設級別。雖然可重複讀取,但會導致“幻像讀”。 能看到某些資料,但無法操作,實際上這部分資料已經被其他事務所更改。

序列化 

serializable

事務A操作資料庫時,資料庫B只能排隊等待。 這種級別可以避免幻像讀,但很少使用,吞吐量太低,使用者體驗差。

04 資料庫優化

4.1 資料庫設計正規化

01.定義

設計關係資料庫時,需要遵從 不同的規範要求 ,以設計出合理的關係型資料庫,這些不同的規範要求被稱為不同的正規化。

02.分類

目前的關係資料庫有 六種正規化 ,分別是: 第一正規化(1NF)、第二正規化(2NF)、第三正規化(3NF)、巴斯-科德正規化(BCNF)、第五正規化(完美正規化)。 正規化越高,意味著表的劃分更細,會降低系統執行效率, 前三種比較比較常用 ,以避免資料操作異常,又不至於表關係過於複雜。

03.前三種正規化介紹

第一正規化(1NF):資料庫表中的每一項都是不可分割的原子資料項,即要求資料庫中的表是二維表每個資料元素不可再分。

比如在國外姓名就不符合第一正規化,因為姓和名可以繼續拆分。

第二正規化(2NF):要設定一個能區分各個記錄的主鍵。

第三正規化(3NF):外來鍵要合理指定依賴欄位,依賴主表主鍵,不要依賴其他欄位即可。

4.2 MySQL 儲存引擎

指的是mysql資料庫管理系統中 用來處理表的處理器

引擎是資料庫管理系統的一部分,是最終完成資料操作的部分,其實就是一段核心程式碼。mysql資料庫是開源的,具有多引擎特徵。

MySQL儲存引擎基本操作
基本操作 語法
檢視所有儲存引擎 show engines;

檢視已有表的儲存引擎

show create table 表名;
建立表指定 create table 表名(...)engine=引擎;
已有表指定 alter table 表名 engine=引擎;
MySQL常用儲存引擎
引擎名 特點
InnoDB

1.支援 行級鎖 ,僅對指定的記錄加鎖, 其他程序可以對同一個表中的 其他記錄 進行操作

2.支援外來鍵、事務、事務回滾。

3.表字段和索引同儲存在一個檔案中。

表名.frm:表結構

表名.ibd:表記錄及索引檔案

4.適用場景: 執行寫操作較多的表

MyISAM

1.支援 表級鎖 ,在 表鎖定期間,其他程序無法對該表進行寫操作 ,如果你是寫鎖(寫操作時上鎖),其他程序讀也不允許。

2.表字段和索引分開儲存。

表名.frm:表結構

表名.MYI:索引檔案(my index)

表名.MYD:表記錄(my data)

3.適用場景: 執行查操作較多的表 ,InnoDB比較浪費資源。

例項1.檢視所有儲存引擎

多客戶端同時操作資料的情況下,用InnoDB比較多,因為它支援事務。

相較於表級鎖,行級鎖每換一次行就要上一次鎖,操作比較頻繁,會消耗比較多的記憶體。

例項2.檢視已有表的儲存引擎

引擎是以表為單位的,建立表時可以指定引擎。

例項3.已有表更改引擎

不同引擎對資料的儲存不同,InnoDB把資料儲存到兩個檔案中,一個用來儲存表結構,另一個用來儲存表記錄和索引檔案。

MyISAM則把資料分別儲存到3個檔案中,分別儲存表結構,索引檔案和表記錄。

4.3 欄位資料型別和鍵的選擇

1.資料型別優先程度

數字型別--> 時間日期型別  --> 字串型別

2.同一級別

佔用空間小的-->佔用空間大的

比如能用tinyint(佔1個位元組),就不用int(佔3個位元組)。

為什麼要優先選擇佔用空間小的資料型別呢?和資料的查詢有關,資料佔用空間越小,查詢時遍歷磁碟的時間就會越短,讀寫處理就更快。

3.優化建議

(1)給InnoDB 設定主鍵 ,使用者不設定,它自己也會設定隱含的主鍵。

(2)儘量 設定佔用空間小的欄位為主鍵

(3)建立外來鍵會自動建立索引,在表關聯查詢時建議 使用外來鍵欄位作為關聯條件

注:外來鍵雖然可以保證資料完整性,但是會降低資料匯入和操作效率,增加維護成本。

4.4 explain語句

01.含義

使用explain關鍵字可以 模擬優化器執行SQL查詢語句 ,從而瞭解mysql是如何處理我們的sql語句的。可以幫助我們分析查詢語句或表結構的效能瓶頸。

02.語法

explain select * from 表名 where 條件;

03.標題

explain主要欄位解析
欄位 說明
table 當前表名
type

顯示查詢使用了何種型別, 從最好到最差的連線型別 分別是system,const,eq_reg,ref,range,index,al l

一般來說,得保證 查詢至少達到range級別,最好能達到ref

system,const : 可以將查詢到的變數轉為常量, 如id=1

id為 主鍵或唯一鍵.

eq_reg :訪問索引,返回某單一行資料

ref : 訪問索引,返回某個值的資料,(可以返回多行) 通常 使用=時 發生

range : 使用索引返回一個範圍中的行,比如 使用>或<查詢東西 ,並且該欄位上建有索引時發生的情況

index : 以索引的順序進行全表掃描

all : 全表掃描, 應儘量避免

possible_keys 顯示可能用在這張表上的索引
key 實際使用的索引
key_len 使用的索引的長度,不失準確性的情況下,越短越好
rows mysql認為必須檢索的用來返回請求資料的行數

例項1. 執行explain select * from 表名 查詢語句

books全表共有6條記錄,執行explain select * from 表名 時,rows顯示數字為6,表示對全表進行了掃描,從type欄位下的ALL也可以看出來。其實全表掃描是最差的一類查詢,工作中我們往往根據條件進行查詢。

例項2. 使用索引查詢

books表有兩個索引,一個是id欄位的主鍵索引,一個是bname欄位的普通索引。

操作1: explain select * from books  where id<5;

此時type欄位顯示使用的是 range型別 的查詢

操作2: explain select * from books  where id=5;

此時type欄位顯示使用的是 const 型別 的查詢

操作3: explain select * from books  where bname='邊城';

此時type欄位顯示使用的是 ref 型別 的查詢

4.5 SQL優化

  1. 儘量選擇資料型別佔空間少 ,在where,group by,order by中出現頻率高的欄位建立索引。

  2. 儘量避免使用select * ,建議把*替換成具體欄位,不要返回用不到的任何欄位。

  3. 儘量控制使用自定義函式 。因為內建函式基本都是用c++寫的,自定義函式我們基本上是用sql寫的,大量使用可能會降低效率。

  4. 查詢最後新增LIMIT會停止全表掃描。

  5. 儘量避免NULL值判斷 ,否則會進行全表掃描預設值為空時可以用用預設0代替。where number=null →where number=0

  6. 儘量避免or連線條件 ,否則會放棄索引進行全表掃描,可以用union代替。where id=1 or where id=2→where id=1 union where id=2

  7. 儘量避免使用in和not in ,否則會全表掃描。where id in (1,2,3,4)→where id between 1and 4

4.6 表的拆分

當單張表查詢資料過大時,查詢效率會變低,這時需要將一張大表拆分成多個小表。有兩種拆表的方法:

1.垂直拆分

表中的列太多,分成多個表,每個表是其中的幾列。將經常查詢的放到一起,blob或者text型別欄位放到另外一個表。

2.水平拆分

減少每個表的資料量,通過關鍵字進行劃分,然後拆成多個表。

05 資料庫安全和管理

資料庫安全和管理
類別 語法
表的複製 create table 新表名 select 查詢命令;
資料庫備份

備份命令格式

mysqldump  -u 使用者名稱 -p 源庫名 > 新庫名.sql

注:>表示匯出符號,兩個庫名儘量設定成一樣的

恢復命令格式:

mysql -u root -p 目標庫名 < 源庫名.sql

MySQL遠端連線

更改配置檔案,重啟服務!

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;

新增使用者和授權

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.刪除使用者

delete user '使用者名稱'@'%'

注:

1.identified by "123456" mysql 8.0版本以後不用寫

2.with grant option 表示該使用者可以繼續向下分配許可權

3.庫.表:    *.*   (表示所有庫的所有表和檢視)

庫.*  (表示這個庫的所有表和檢視)

例項1.表的複製

複製新表並檢視是否存在

查看錶結構,新表沒有設定主鍵

例項2.資料庫備份

資料庫備份功能是mysql資料庫自帶的軟體功能,不屬於sql語句,所以不能在資料庫的互動模式下寫。(在終端執行)

例項3.恢復命令格式

上面已經備份了stu庫的資訊,現在把stu庫刪了,看能不能從備份檔案中把資料複製回來

例項4.mysql遠端連線

root擁有對資料庫的最高許可權,在公司中,根據業務和職權大小的差異,還會為其他使用者設定不同範圍的管理許可權。

通過終端操作資料庫的方法,在 131 python|第四部分:Linux作業系統 中提到過ssh服務,除此之外,mysql資料庫系統本身也提供了一個獨立的遠端訪問伺服器的方法。

以訪問自己的伺服器舉例,首先通過ifconfig檢視ip地址

在未進行配置之前,會報錯(報錯圖片略)

步驟1.開啟配置檔案

步驟2.更改配置檔案

步驟3.重啟mysql

在程式啟動時,會自動讀取配置檔案,所以修改配置檔案後,需要重啟一下

步驟4.進入mysql修改使用者表host值

步驟5.重新整理許可權

遠端連線成功

例項5.新增使用者和授權

步驟1.用root使用者登入mysql(圖略)

步驟2. 新增使用者test

在為新使用者設定許可權之前,只有一個數據庫,用來描述資料庫系統資訊。

步驟3.許可權管理

3.1給新使用者設定許可權

也可以繼續為新使用者新增許可權,會在原來許可權的基礎上累加

3.2給新使用者刪除許可權

test使用者的更新許可權被刪除後,無法進行更新操作

步驟4.重新整理許可權   flush privileges;(圖略)

步驟5.刪除許可權

06 pymysql模組

在128 python|第三部分:python高階(一)程式結構和異常處理 中提到python的模組分為4種類型,在那篇文章中主要介紹了前兩種型別,即內建模組和標準庫模組中的time模組。接下來要學習的pymysql模組是python模組的第3種——第三方模組中的一種。

第三方模組一般需要使用者在安裝python後自行安裝,安裝命令如下:

sudo pip3 install 第三方模組名

注:pip3是python安裝第三方模組的工具,python的 3.5版本之後 安裝時自帶,下載python後無需重新安裝。另外,pip3是一個通用工具,在windows和MacOs下都可以使用。

         

6.1 pycharm新建專案

在pycharm中建立專案(file-->new project)時需要注意,彈出的頁面中有兩個選項:

第1個選項表示建立一個新的虛擬打包環境。

這意味著pycharm中只有標準庫,沒有第三方庫,用到第三方庫時,需要重新安裝。

選擇這種環境的 好處 是, 讓開發更純淨 ,比如工作中同時開發多個專案時,這些專案用到的第三方庫有所不同, 專案結束後,要把環境連同程式碼一起打包,選擇第1種不會把無關的東西打包進去,實際的開發中一部分程式設計師會傾向於選擇這種環境。

第2個選項表示自動使用系統環境 , 即python裝好的庫在pycharm中都能使用。

如果選擇的是第一種,在專案根目錄中會多出一個venv檔案。如果已經通過第1種環境新建好了檔案,臨時想要改成第2種,可以在專案根目錄找到並刪除venv檔案,然後再次開啟檔案即可。

6.2 pymysql 模組

01.pymysql使用流程

1.建立資料庫連線 db=pymysql.connect(...)
2.建立遊標物件 cur=db.cursor()
3.遊標方法 cur.execute("insert...")
4.提交到資料庫或者獲取資料:db.commit()/cur.fetchall()
5.關閉遊標物件 cur.close()
6.斷開資料庫連線 db.close()
注:遊標指的是用於執行sql語句得到執行結果的變數

pymysql的使用可以像檔案讀寫一樣,形象化地理解為,“把大象關冰箱需要幾步”。步驟和步驟2視為開冰箱門,步驟3和步驟4視為把大象塞進冰箱,步驟5和步驟6視為關上冰箱門。

02.常用函式

開冰箱門 

db=pymysql.connect(引數列表)
功能:連線資料庫
host:主機地址,本地:localhost
port:埠號,預設:3306
user:使用者名稱
password:密碼
database:庫
charset:編碼方式,推薦使用utf8


cur=db.cursor()
功能:建立遊標
返回值:返回遊標物件,用於執行具體SQL命令

把大象塞進冰箱

cur.execute(sql,args_list)
功能:執行SQL命令
引數:sql sql語句
args_list 列表,用於給sql語句傳遞參量

cur.executemany(sql命令,args_list)
功能:多次執行SQL命令,執行次數由列表中元組數量決定
引數:sql sql語句
args_list 列表中包含元組,每個元組用於給sql語句傳遞參量,一般用於寫操作
注:第2種方式相當於在遊標方法內部寫了個for迴圈,會自動把args_list 中的元素一一傳給sql語句執行
db.commit() 提交到資料庫執行,必須支援事務操作才有效
db.rollback() 回到原來的資料形態,必須支援事務操作才有效
cur.fetchone() 獲取查詢結果集的第一條資料,查詢到返回一個元組,否則返回None
cur.fetchmany(n) 獲取前n條查詢到的記錄,返回結果為元組巢狀元組
((記錄1),(記錄2)) 查詢不到內容返回空元組
cur.fetchall() 獲取所有查詢到的記錄,返回結果形式同上

關上冰箱門

cur.close() 關閉遊標物件
db.close() 關閉資料庫連線

03.例項

例項1.pymysql基礎使用流程示例(寫操作)

先建一個pymysql的流程

加入寫操作,並執行

在終端檢視class表,發現並沒有寫入成功

接下來換張hobby表寫入試試

寫入成功

原因在於, 使用mysql操作資料庫時

1.如果資料表不支援事務,則execute執行語句會立即生效

2.如果資料表支援事務,則需要commit() 或rollback()操作

在上面的操作中,class表的引擎是InnoDB,支援事務;hobby表的引擎是myisam,不支援事務。對class標進行 寫入後,沒有通過commit結束事務,所以資料並沒有傳入到資料庫中,也就無法顯示出寫入後的資料。

myisam不支援事務,execute執行語句立即生效,在資料表中能夠立即看到寫入後的資料。

加上commit執行試試

class表也寫入成功

進一步優化,加入try...except...

使用 cur.execute(sql,args_list)args_list 引數,讓sql語句的寫入更加靈活

使用 cur.executemany(sql命令,args_list)批量插入資料

例項2. 新建庫並插入資料(寫操作)

面向過程的寫法:

# 需求
建立一個新的資料庫 dict 使用utf8編碼
在該資料庫下建立一個數據表 words : id word mean
使用dict.txt檔案,將其中的單詞插入到words資料表


1.建立資料庫dict
create database dict charset=utf8;


2.建立資料表words
use dict;
create table words(
id int primary key auto_increment,
word varchar(30) not null,
mean text
);
注:步驟1和步驟2在終端的mysql中操作


#以下步驟在Pycharm中操作


3.給表插入dict.txt中的資料
思路:開啟檔案dict.txt-->提取單詞和解釋-->組織資料-->插入到資料表words


#匯入模組
import pymysql
import re


#連線資料庫
kwargs = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "123456",
"database": "dict",
"charset": "utf8"
}
db = pymysql.connect(**kwargs)
#生成遊標
cur = db.cursor()


#儲存單詞[(word,mean),(word,mean)...]
data = []
#開啟檔案
fr = open("dict.txt",'r')


#遍歷檔案,每次讀取一行
for line in fr:
#用正則表示式獲取(word,mean)
data += re.findall("(\w+)\s+(.*)",line)
#關閉檔案
fr.close()


#批量插入
sql="insert into words (word,mean) value(%s,%s);"
cur.executemany(sql,data)#多次執行sql
db.commit()


#關閉資料庫操作
cur.close()
db.close()

1.建立資料庫並建立資料表

2.寫好程式並執行

3.資料庫查看錶資料 select * from words;

面向物件的寫法:

#匯入pymysql
import pymysql
import re


class Dict():
#建立Dict()的同時會初始化物件,連線資料庫
def __init__(self):
#連線資料庫
self.kwargs = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "123456",
"database": "dict",
"charset": "utf8"
}


self.db = pymysql.connect(**self.kwargs)
#生成遊標
self.cur = self.db.cursor()


def get_data(self):
#獲取資料
data = []
fr = open("dict.txt",'r')


for line in fr:
# target = line.split(" ",1)
# return line
data += re.findall("(\w+)\s+(.*)",line)
fr.close()
return data


def insert_data(self):
#插入資料
data =self.get_data()#獲取資料
sql="insert into words (word,mean) value(%s,%s);"
self.cur.executemany(sql,data)
self.db.commit()


def close(self):
#關閉資料庫
self.cur.close()
self.db.close()


if __name__ == '__main__':
dict = Dict() #建立例項物件Dict()
dict.insert_words() #插入資料
dict.close() #關閉檔案

和麵向過程一樣可以完成相同的插入單詞操作。

例項3. 資料庫讀操作示例

#匯入pymysql
import pymysql
import re


#連線資料庫
kwargs = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "123456",
"database": "stu",
"charset": "utf8"
}
db = pymysql.connect(**kwargs)
#生成遊標
cur = db.cursor()


#資料庫讀操作 在程式中讀資料庫中的資料,然後在程式中運用資料
sql = "select name,age,score from class where score>%s;"
cur.execute(sql,[20])


#獲取查詢結果


#查詢操作1:迭代取值
for row in cur:
print(row)
#查詢操作2:獲取一個查詢記錄
one = cur.fetchone() #結果 元組() 或None
print('one:',one)


#查詢操作3:獲取兩個查詢記錄(取記錄的時候,取一個會少一個,從上次取的位置往下繼續取)
many = cur.fetchmany(2)
print('many:',many)


#查詢操作4:獲取所有查詢記錄
all = cur.fetchall()
print('all:',all)


#注:資料庫的讀操作不會開啟事務,不用寫結束事務
#關閉資料庫
cur.close()
db.close()

查詢操作1:迭代取值查詢結果(顯示錶中所有滿足條件的資料)

查詢操作2:獲取一個查詢記錄

查詢操作3:獲取兩個查詢記錄

查詢操作4:獲取所有查詢記錄

例項4. 使用資料庫中的表(class表)儲存圖片並讀取

1.給class表增加欄位image

2.在程式中存入圖片(寫操作)並執行程式

#匯入pymysql
import pymysql
import re


#連線資料庫
kwargs = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "123456",
"database": "stu",
"charset": "utf8"
}
db = pymysql.connect(**kwargs)
#生成遊標
cur = db.cursor()


#存入圖片
with open("/home/huanhuan/下載/food.jpg",'rb') as fr:
data = fr.read()

#給class表中的第一個人插入圖片
sql = "update class set image=%s where id=1;"
cur.execute(sql,[data])
db.commit()


#獲取圖片
sql = "select name,image from class where id=1"
cur.execute(sql)
name,image = cur.fetchone() #(name,image )
with open("%s.jepg"%name,'wb') as fw:
fw.write(image)


cur.close()
db.close()

3.在終端檢視儲存記錄

4.獲取圖片

下期預告:併發網路程式設計部分

花樣早餐