欲直接下載代碼文件,關注咱們的公衆號哦!查看歷史消息便可!python
本文介紹如何利用python來對MySQL數據庫進行操做,本文將主要從如下幾個方面展開介紹:mysql
1.數據庫介紹sql
2.MySQL數據庫安裝和設置數據庫
3.Python操做MySQLwindows
在Python3.X上安裝MySQL驅動python3.x
建立數據庫鏈接服務器
建立數據表網絡
增、改、刪、查數據結構
分組、聚合app
按批量讀取和處理數據
4.小結
數據庫(Database)是按照數據結構來組織、存儲和管理數據的倉庫,能直接經過條件快速查詢到指定的數據。隨着信息技術和市場的發展,數據管理再也不僅僅是存儲和管理數據,而轉變成用戶所須要的各類數據管理的方式。
目前,數據庫主要有兩種形式,一種是非關係型數據庫,另外一種是關係型數據庫。目前,咱們用得很是普遍的一種數據庫類型是關係型數據庫,它能夠分爲如下幾種:
Oracle:
付費產品,主要是銀行在用(萬一出錯了有Oracle背鍋)
DB2:
付費產品,IBM產品
SQL Sever:
付費產品,微軟產品,windows專用
PostgreSQL:
免費產品,主要是高校學術上使用
MySQL:
大衆,免費,開源
做爲手無寸金的大學生,咱們應該用哪一種數據庫呢?固然是MySQL。一方面是由於MySQL免費,另外一方面是由於普及率最高,出了錯,能夠很容易找到解決方法。並且,圍繞MySQL有一大堆監控和運維的工具,安裝和使用很方便。因此,本文接下來也會介紹如何用Python來操做MySQL。
STEP1:MySQL官方網站上下載最新的MySQL Installer 8.0.14版本,下載連接爲:
STEP2:按照指示操做默認安裝,在安裝時,MySQL會要求咱們設置一個本地登錄帳號,帳號名通常命爲root,端口爲3306,自定義一個password便可。
至此,咱們完成了MySQL中用戶的新建和受權。
目前,關於Python操做數據庫主要有如下幾種方法:
MySQLdb是用於Python鏈接MySQL數據庫的接口,它實現了Python數據庫API規範V2.0,基於MySQL C API上創建的,目前只支持Python2.x。
PyMySQL是Python中用於鏈接MySQL服務器的一個庫,它支持Python3.x,是一個純Python寫的MySQL客戶端,它的目標是替代MySQLdb。PyMySQL在MIT許可下發布。
因爲 MySQL 服務器以獨立的進程運行,並經過網絡對外服務,因此,須要支持 Python 的 MySQL 驅動來鏈接到 MySQL 服務器。
目前,有兩個 MySQL 驅動:
mysql-connector-python:是 MySQL 官方的純 Python 驅動
MySQL-python :是封裝了 MySQL C驅動的 Python 驅動
是一種ORM(Object-Relational Mapping)框架,將關係數據庫的表結構映射到對象上,隱藏了數據庫操做背後的細節,簡化了數據操做。
STEP1:因爲MySQL官方提供了mysql-connector-python驅動。安裝時,在Anaconda Prompt中輸入:
conda install mysql-connector-python
STEP2:使用如下代碼來測試mysql-connector是否安裝成功:
import mysql.connector
若是沒有產生錯誤,則代表安裝成功。
這裏鏈接的是我以前建立的blank這個user。若是數據庫已經存在的話,咱們能夠直接鏈接;若是數據庫不存在,直接鏈接則會報錯,這個時候咱們就須要建立一個數據庫,建立數據庫能夠在MySQL Workbench中建立,也能夠在python中使用"CREATE DATABASE"語句,在本實驗中,咱們使用已經在MySQL workbench中已經建好的test_s這個數據庫。
import mysql.connector #鏈接數據庫 config = { 'user' : 'blank' #用戶名 'password' : 'password' #本身設定的密碼 'host' : '127.0.0.1' #ip地址,本地填127.0.0.1,也能夠填localhost 'port' : '3306' #端口,本地的通常爲3306 'database' : 'test_s' #數據庫名字,這裏選用test_s } con = mysq;.connector.connect(**config)
cursor():表示遊標
execute():是執行語句
# 建立一個表 # buffered = True 不設的話,查詢結果沒有讀完會報錯 # raise errors.InternalError("Unread result found") mycursor = con.cursor(buffered = True) mycursor.execute("CREATE TABLE customers(id INT AUTO_INCREMENT PRIMARY KEY, \ name VARCHAR(255) , address VARCHAR(255), \ 7sex VARCHAR(225) , age INT(10) , sl INT(10))")
VARCHAR()表示的是數據類型,定義的是變長字符串;INT()表示整型
STEP4:可是,當咱們再次執行語句的時候,因爲已經建立了"customers"這個表,因此再次執行會報錯,這個時候就須要加一個判斷,判斷這個表是否已經存在於test_s這個數據庫中
ProgrammingError: Table 'customers' alreadyy exists
STEP5:咱們能夠用"SHOW TABLES"語句來查看數據表是否已經存在,若是存在就print"table already exists",若是不存在,就print"table does not exist"。
def tableExists(mycursor, name): stmt = "SHOW TABLES LIKE '" +name+ "'" mycursor.execute(stmt) return mycursor.fetchone() mycursor = con.cursor() if tableExists(mycursor , 'customers'): print("table already exists") else: print("table not exists")
import mysql.connector #鏈接數據庫 config = { 'user' : 'blank', 'password' :'fuying123888', 'host' : '127.0.0.1', 'port':'3306', 'database' : 'test_s' } con = mysql.connector.connect(**config) # 檢查一個表是否存在 def tableExists(mycursor, name): stmt = "SHOW TABLES LIKE '"+name+"'" mycursor.execute(stmt) return mycursor.fetchone() # 刪除一個表(不管它是否已經存在) def dropTable(mycursor, name): stmt = "DROP TABLE IF EXISTS "+name mycursor.execute(stmt) # buffered=True 不設的話,查詢結果沒有讀完會報錯 # raise errors.InternalError("Unread result found") mycursor = con.cursor(buffered=True) # 刪除臨時表 tableName = 'customers' dropTable(mycursor, tableName) # 建立一個表 mycursor.execute("CREATE TABLE customers(id INT AUTO_INCREMENT PRIMARY KEY,\ name VARCHAR(255), address VARCHAR(255), \ sex VARCHAR(225), age INT(10), sl INT(10))")
在cutomers表中插入數據用的是"INSERT INTO"語句。
除了用一條條用execute( )插入以外,咱們還能夠用executemany()的方式批量插入,也就是val中包含的是一個元組列表,包含咱們想要插入的數據。
須要注意的事是:若是數據表格有更新,那麼必須用到commit()語句,不然在workbench是看不到插入的數據的。
# 往表裏插入一些記錄 sql="INSERT INTO customers(name,address,sex,age,sl) VALUES(%s, %s,%s,%s,%s)" val = ("John", "Highway 21","M",23,5000) mycursor.execute(sql, val) val = ("Jenny", "Highway 29","F",30,12500) mycursor.execute(sql, val) val=[("Tom","ABC 35","M",35,14000), ("Tom1","Highway 29","M",28,6700), ("Lily","Road 11","F",30,8000), ("Martin","Road 24","M",35,14000), ("Sally","Fast 56","M",32,15000)] mycursor.executemany(sql, val) con.commit()
執行以上代碼後,回到workbench,,咱們能夠看到最終的結果爲:
在cutomers表中更改數據用的是"UPDATE"語句。例如,咱們將最後一條 「Sally」的名字改爲「Tiny」:
# 將Sally改成Tiny sql="UPDATE customers SET name='Tiny' WHERE name ='Sally'" mycursor.execute(sql) con.commit()
執行代碼,回到workbench咱們能夠看到結果爲:
關於刪,咱們在上文提到了刪除表格,用的是「DROP TABLE 」語句,「IF EXISTS」關鍵字是用於判斷表是否存在,只有在存在的狀況才刪除當咱們要刪除一條數據記錄時候,用到的語句是「DELETE FROM」語句。例如:咱們想在customers這個表格當中,刪除name爲Tiny的這一條記錄:
#刪除名字爲Tiny的記錄 sql="DELETE FROM customers WHERE name='Tiny'" mycursor.execute(sql) con.commit()
執行代碼,回到workbench咱們能夠看到結果爲:
普通查詢數據用的是SELECT語句。例如:咱們想查詢customers的全部信息,而且進行打印輸出:
#查詢這裏面全部的人: sql="SELECT * FROM customers" mycursor.execute(sql) myresult = mycursor.fetchall() # fetchall() 獲取全部記錄 for x in myresult: print(x)
獲得最終結果爲:
值得注意的是:fetchall()表示的是得到全部記錄;fetchone()表示只獲取一條數據;fetchmany(size=3)表示獲取三條記錄;
爲了獲取指定條件下的查找結果,咱們可使用where語句。例如:咱們想在查詢customers的全部信息基礎上,輸出年齡大於30歲的消費者的信息:
sql="SELECT * FROM customers WHERE age > 30" mycursor.execute(sql) myresult = mycursor.fetchall() # fetchall() 獲取全部記錄 for x in myresult: print(x)
最終獲得的結果爲:
有時候爲了進行模糊查詢,能夠匹配通配符,經過「LIKE」來進行查找:
百分號 (%):表明零個、一個或多個數字或字符;
下劃線 (_):表明一個單一的數字或字符。
例如:查出全部名字中含有t的記錄:
#%表明零個、一個或者多個數字或字符 #_表明一個單一的數字或者字符 sql = "SELECT * FROM customers WHERE name LIKE '%t%'" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
執行代碼,咱們獲得的結果以下:
值得注意的是:可是使用Like查詢時,即便咱們在代碼輸入的是「t」,執行過程當中也會將含有「T」的記錄一樣輸出,即用LIKE匹配通配符對大小寫不敏感。爲了區分大小寫,能夠用「GLOB」進行查詢。
查詢結果排序可使用 ORDER BY 語句,默認的排序方式爲升序,若是要設置降序排序,能夠設置關鍵字 DESC。例如:咱們要按照年齡對customers進行升序排列:
#排序 #按照年齡排序 sql = "SELECT * FROM customers ORDER BY age" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
執行代碼,獲得的結果爲:
n zxx m nb
當數據庫數量很是大的時候,爲了限制查詢的數據量,能夠採用"LIMIT"語句來指定,好比咱們但願在customers表中找出工資最高的三我的:
#找出其中工資最高的3我的 sql = "SELECT * FROM customers ORDER BY sl DESC LIMIT 3" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
執行代碼,獲得結果爲:
有時候咱們在進行一次篩選後,還須要設定一個篩選條件進行二次篩選,咱們就能夠採用「HAVING」語句。例如:咱們但願統計在年齡處於20-30(不包括20歲,可是包括30歲)的人當中,選擇薪資大於5000的消費者:
#二次過濾 #統計在年齡處於20-30之間的人中,選擇薪資大於5000的人 sql = "SELECT * FROM customers WHERE age>20 and age<=30 HAVING sl>5000 " mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x) con.commit() con.close()
執行代碼後,獲得的結果以下:
在數據庫中,分組經常使用的語句爲「GROUP BY」語句,聚合函數,一般是配合分組進行使用,在數據庫中經常使用的聚合函數爲:
COUNT(*):表示計算總行數,括號能夠寫*和字段名字
MAX(column):表示求此列的最大值
MIN(column):表示求此列的最小值
SUM(column):表示求此列的和
AVG(column):表示求此列的平均值
以sex爲類別進行GROUP BY 分組,加上WHERE來作條件判斷。
#統計出男女的薪水總數 sql = "SELECT sex,sum(sl) FROM customers GROUP BY sex" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
最終結果爲:
# 按照性別進行分組,統計出年齡在20-30歲的消費者的薪資 sql = "SELECT sex,sum(sl) FROM customers WHERE age>20 and age<=30 GROUP BY sex ORDER BY sl" mycursor.execute(sql) myresult=mycursor.fetchall() for x in myresult: print(x)
值得注意的是:本例是以sex爲類別進行GROUP BY 分組,加上WHERE來作條件判斷,加上ORDER BY 排序,可是GROUP BY 的位置必需要在WHERE 以後,在ORDER BY 以前。
程序運行的時候,數據都是在內存中的,可是有時候若是數據量太大,內存會裝不下,這個時候咱們就須要分批從數據庫去讀取數據,而後再處理,等處處理完了以後,再去讀取。好比:咱們要從customers當中分批讀取和處理薪資大於8000的消費者,並將其存入另外一張表中。咱們的作法是先新建一個表,而後從數據庫當中讀取3個,而且將讀取的這3個進行處理,處理完讀取的這三個後,再去數據庫從新讀取三個,直到數據庫的數據讀完爲止。
# 分批讀取而且處理將薪資大於8000的消費者的記錄存到另外一張表中 # 建立一個臨時表 tmpName = 'cust_tmp' dropTable(mycursor, tmpName) mycursor.execute("CREATE TABLE cust_tmp(id INT AUTO_INCREMENT PRIMARY KEY,\ name VARCHAR(255), address VARCHAR(255), \ sex VARCHAR(225), age INT(10), sl INT(10))") ins = con.cursor(buffered=True) if tableExists(mycursor, tableName): print("process table: %s", tableName) # 查詢表裏的記錄 sql = "SELECT * FROM customers WHERE address is not null" mycursor.execute(sql) # 每次處理 batchsize 條記錄,直到全部查詢結果處理完 batchsize = 3 readsize = batchsize while readsize == batchsize: print("before batch") myresult = mycursor.fetchmany(size=batchsize) for x in myresult: if x[5]>8000: ins.execute("INSERT INTO"+tmpName+"(id,name,address,sex,age,sl) VALUES (%s, %s,%s, %s,%s,%s)", x) print(x) readsize = len(myresult) else: print("table: does not exists", tableName) con.commit() con.close()
咱們回到workbench找到這個新建的表格cust_tmp,咱們能夠發現薪資大於8000的消費者都被記錄上了:
執行代碼,咱們能夠看處處理的過程以下:
在第一批讀取的三條記錄中,只有兩條是知足薪資大於8000的要求,第二批讀取的三條記錄中,只有一條知足薪資大於8000的要求,而在第三批讀取的三條記錄中,沒有任何記錄是知足薪資大於8000的要求,當沒有記錄能夠讀的時候,程序即中止。
值得注意的是:就分批讀取的batchsize而言,當batchsize太大時,會致使內存裝不下,batchsize過小,會致使每次經過網絡鏈接數據庫會很慢。所以,咱們選取batchsize大小的原則是在內存夠用的前提下儘量的大,在真實的業務場景下,建議每次讀取100以上,當內存夠用的話,也能夠增長至幾千上萬條。
本文介紹了Python+MySQL的基本操做,包括如何安裝Mysql,如何裝驅動,如何建立鏈接以及對數據庫進行增刪改查、分組聚合以及批量讀取和處理等操做。可是,本文涉及到的只是對單表進行操做,只是數據庫操做的冰山一角;在實際的開發和工做環境中,須要根據實際內容對多表進行操做,這部分請持續關注數據魔術師關於數據庫的後期推文。