1. 程式人生 > >python3操作MySQL資料庫

python3操作MySQL資料庫

這是python3下的MySQL基本操作。其他型別的資料庫用法基本一樣。就是庫的名字不同。因為python官方很早之前就規定了資料庫第三方庫的藉口,來避免API混亂的情況。

安裝與準備

這是python3的庫,所以windows下安裝不會像python2那樣各種奇葩VC錯誤。是比較方便的傻瓜安裝。

  • Windows平臺下: py -3 -m pip install PyMySQL
  • Linux:python3 pip install PyMySQL

當然,引入的時候:import pymysql

資料庫連線物件connection

Function 描述
connection 建立connection物件
cursor() 使用該連結建立+返回遊標
commit() 提交當前事務
rollback() 回滾當前十五
close() 關閉連線

介紹一下connection的引數

  1. host mysql伺服器地址
  2. port 數字型別 埠
  3. user 使用者名稱
  4. passwd 密碼
  5. db 資料庫名稱
  6. charset 連線編碼,需要顯式指明編碼方式

上一段程式碼示例:

conn = pymysql.Connect(host='127.0.0.1',port=3306,user='root',passwd='dyx240030',db='imooc',charset='utf8')
cursor = conn.cursor()
print(conn)
print(cursor)
cursor.close()
conn.close()
OUT:
<pymysql.connections.Connection object at 0x00000051C15BFDA0>
<pymysql.cursors.Cursor object at 0x00000051C15BFD68>

資料庫遊標物件cursor

Function 描述
execute(op[,args]) 執行一個數據庫查詢和命令
fetchone() 取得結果集下一行
fetchmany(size) 取得結果集size行
fetchall() 取得結果集剩下所有行
rowcount 最近一次execute返回資料的行數或影響行數
close() 關閉cursor

程式碼實現:

conn = pymysql.Connect(host='127.0.0.1',port=3306,user='root',passwd='dyx240030',db='imooc',charset='utf8')
cursor = conn.cursor()
sql = "select * from user"
cursor.execute(sql)
print("cursor.excute:",cursor.rowcount)

rs = cursor.fetchone()
print("rs:",rs)

for each in cursor.fetchmany(2):
    print(each)
print()
for each in cursor.fetchall():
    print(each)
OUT:
cursor.excute: 4
rs: ('1', 'name1')
('2', 'name2')
('3', 'name3')

('4', 'name4')

更新資料庫insert/update/delete

不同於select操作,這三個操作修改了資料庫內容,所以需要commit(),否則資料庫沒有做相應的更改,但是也不會報錯。

按照一般的思路,一般是以下套路:

  1. 關閉自動commit:conn.autocommit(False)
  2. 出現:conn.rowback()回滾
  3. 未出現:conn.commit()

下面這段指令碼,實現insert/update/delete操作。其實這種檢錯模式不對,這裡只做簡單raise,後面有更好的方法。

conn = pymysql.Connect(host='127.0.0.1',port=3306,user='root',passwd='dyx240030',db='imooc',charset='utf8')
conn.autocommit(False)
cursor = conn.cursor()

sqlInsert = "insert into user(userid,username) values('6','name6')"
sqlUpdate = "update user set username='name41' where userd='4'"
sqlDelete = "delete from user where userid='1'"
try:
    cursor.execute(sqlInsert)
    print(cursor.rowcount)
    cursor.execute(sqlUpdate)
    print(cursor.rowcount)
    cursor.execute(sqlDelete)
    print(cursor.rowcount)
    
    conn.commit()
except Exception as e:
    print("Reason:",e)
    conn.rollback()
    
cursor.close()
cursor.close()
[OUT]:
1
Reason: (1054, "Unknown column 'userd' in 'where clause'")

例項 銀行轉賬

可以看一下類思想的SQL操作,其中之前提到過的高階報錯模式用到了之前看似無用的rowcount函式,通過檢視操作對於資料庫的影響來檢錯。

import os
import sys
import pymysql

class transferMoney(object):
    def __init__(self,conn):
        self.conn = conn
    def transfer(self,sourceID,targetID,money):
        #   其他函式中若是有錯會丟擲異常而被檢測到。
        try:
            self.checkIdAvailable(sourceID)
            self.checkIdAvailable(targetID)
            self.ifEnoughMoney(sourceID,money)
            self.reduceMoney(sourceID,money)
            self.addMoney(targetID,money)
            self.conn.commit()
        except Exception as e:
            self.conn.rollback()
            raise e
    def checkIdAvailable(self,ID):
        cursor = self.conn.cursor()
        try:
            sql = "select * from account where id = %d" % ID #select語句判斷可以用len(rs)
            cursor.execute(sql)
            rs=  cursor.fetchall()
            if len(rs) != 1:#   資料庫類思想的報錯模式,檢查操作對資料庫的影響條目。沒有達到目標,丟擲異常
                raise Exception("賬號 %d 不存在"%ID)
        finally:
            cursor.close()
        
    def ifEnoughMoney(self,ID,money):
        cursor = self.conn.cursor()
        try:
            sql = "select * from account where id = %d and money>=%d" % (ID,money)
            cursor.execute(sql)
            rs=  cursor.fetchall()
            if len(rs) != 1:
                raise Exception("賬號 %d 不存在 %d Yuan"%(ID,money))
        finally:
            cursor.close()
    
    def reduceMoney(self,ID,money):
        cursor = self.conn.cursor()
        try:
            sql = "update account set money = money-%d where id=%d"%(money,ID)
            cursor.execute(sql)
            if cursor.rowcount != 1:
                raise Exception("失敗減錢")
        finally:
            cursor.close()
    
    def addMoney(self,ID,money):
        cursor = self.conn.cursor()
        try:
            sql = "update account set money = money+%d where id=%d"%(money,ID)
            cursor.execute(sql)
            if cursor.rowcount != 1:
                raise Exception("失敗加款")
        finally:
            cursor.close()
    

if __name__=="__main__":
    if len(sys.argv)>=2:
        sourceID = int(sys.argv[1])
        targetID = int(sys.argv[2])
        money = int(sys.argv[3])

        conn = pymysql.Connect(host='127.0.0.1',port=3306,user='root',passwd='dyx240030',db='imooc',charset='utf8')
        trMoney = transferMoney(conn)

        try:
            trMoney.transfer(sourceID,targetID,money)
        except  Exception as e:
            print("出現問題"+str(e))
        finally:
            conn.close()

我踩過的坑。。。(這裡是Python3哦)

'NoneType' object has no attribute 'encoding' ,之前指明的charset必須是"UTF8",不是"utf-8"/"UTF-8"
MySQL語句後面必須有';',否則不會報錯,也難以發現
資料庫insert/update/delete操作需要commit()
在構造命令的時候,注意用 " 包裹起來,因為SQL語句字串需要 ' 包裹。所以," 比較簡單的避免歧義。