1. 程式人生 > 資料庫 >python連線mysql並進行增刪改查操作

python連線mysql並進行增刪改查操作

查詢了菜鳥教程以及部落格園等各種文章,有修改完善

轉載自https://www.cnblogs.com/yuhou/p/10893056.html

 

自己完善部分:

python連線mysql使用連線池:

一、為什麼要用連線池?

1、資料庫 本身有壓力,並不能建立太多的併發數訪問資料庫,如果是大表那更加會有壓力,因此限制一定的連線是更加科學的方法。
2、建立和釋放資料庫連線是一個很耗時的操作,頻繁地進行這樣的操作將佔用大量的效能開銷,進而響應速度下降,嚴重的時候可能導致伺服器崩潰,資料庫連線池可以節省系統許多開銷。

綜上所述,可以使用連線池當然最好是使用連線池了。

 

二、使用DBUtils包

DBUtils是一套Python資料庫連線池包,並允許對非執行緒安全的資料庫介面進行執行緒安全包裝。DBUtils來自Webware for Python。

DBUtils提供兩種外部介面:

    • PersistentDB :提供執行緒專用的資料庫連線,並自動管理連線。
    • PooledDB :提供執行緒間可共享的資料庫連線,並自動管理連線。
      需要庫
      1、DBUtils pip install DBUtils
      2、pymysql pip install pymysql/MySQLdb 

此處用的是DBUtils 2.0,詳細的請看官方文件

 

with語句的工作原理:此處使用with語句進行操作,自動呼叫with後邊類的返回值,最後呼叫類的exit方法清理

 

緊跟with後面的語句會被求值,返回物件的__enter__()方法被呼叫,這個方法的返回值將被賦值給as關鍵字後面的變數,當with後面的程式碼塊全部被執行完之後,將呼叫前面返回物件的__exit__()方法。

 with語句最關鍵的地方在於被求值物件必須有__enter__()和__exit__()這兩個方法,那我們就可以通過自己實現這兩方法來自定義with語句處理異常。

 

 

import pymysql
from dbutils.pooled_db import PooledDB

#配置檔案,連線資料庫使用,配置連線池相關引數
config = {
'host':'127.0.0.1',
'port':3306,
'user':'root',
'password':"",
'db':'test',
'creator':pymysql,#使用連線資料庫的模組,這裡是mysql,還可以是pgsql,oracle等等
'mincached':1,#啟動時開啟的閒置連線數量(預設值 0 表示開始時不建立連線)
'maxcached':5,#連線池中允許的閒置的最多連線數量(預設值 0 代表不閒置連線池大小)
'maxshared':5,#共享連線數允許的最大數量(預設值 0 代表所有連線都是專用的)如果達到了最大數量,被請求為共享的連線將會被共享使用
'maxconnections':10,#建立連線池的最大數量(預設值 0 代表不限制)
'blocking':True,#設定在連線池達到最大數量時的行為(預設值 0 或 False 代表返回一個錯誤<toMany......> 其他代表阻塞直到連線數減少,連線被分配)
'maxusage':0,# 單個連線的最大允許複用次數(預設值 0 或 False 代表不限制的複用).當達到最大數時,連線會自動重新連線(關閉和重新開啟)
'setsession':None,#一個可選的SQL命令列表用於準備每個會話,如["set datestyle to german", ...]
'charset':'utf8'
}


"""
通過DBUtils,例項化一個PooledDB物件作為MyConnectionPool類的類屬性,
通過重寫__enter__和__exit__方法讓我們在進入with語句時從連線池中獲取到資料庫連線,
通過with語句呼叫,在with語句結束後,自動釋放連線池,歸還給連線池。
"""
class MyConnectionPool(object):

def __init__(self,**kwargs):
self.pool = PooledDB(**config)

# 建立資料庫連線,以及獲取遊標
def __enter__(self):
print("進入enter")
self.conn = self.pool.connection()
self.cursor = self.conn.cursor()
return self

# 釋放連線池資源
def __exit__(self, exc_type, exc_val, exc_tb):
self.cursor.close()
self.conn.close()
print("執行了exit")


#以上就完成了整個流程,建立連線,獲取遊標等
#以上整體可以作為一個工具,作為資料庫連線池

#####################===================================================================================##################
#下邊,具體如何使用資料庫連線池示例
if __name__ == '__main__':
with MyConnectionPool() as db:
db.cursor.execute("select * from review")
db.conn.commit()
for row in db.cursor.fetchall():
print("nid:%d\t created_at:%s\t content:%s\t source:%s" % row)

 

 輸出列印:

進入enter
nid:1 created_at:2020-12-22 content:中文支援嗎 source:啊啊啊啊啊
nid:1 created_at:2020-12-22 content:修改內容 source:啦啦啦
nid:2 created_at:2020-12-22 content:修改內容 source:牛牪犇
nid:3 created_at:2020-12-22 content:修改內容 source:啦啦啦
nid:4 created_at:2020-12-22 content:修改內容 source:中國
nid:5 created_at:2020-12-22 content:修改內容 source:啦啦啦
nid:6 created_at:2022-1-1 content:修改內容 source:啦啦啦
nid:6 created_at:2022-1-1 content:修改內容 source:啦啦啦
nid:7 created_at:2020-12-22 content:修改內容 source:啦啦啦
執行了exit

 

 

 

來源:https://www.cnblogs.com/woider/p/5926744.html

==================pymysql===================

由於 MySQLdb 模組還不支援 Python3.x,所以 Python3.x 如果想連線MySQL需要安裝 pymysql 模組。

 

pymysql 模組可以通過 pip 安裝。但如果你使用的是 pycharm IDE,則可以使用 project python 安裝第三方模組。

 

[File] >> [settings] >> [Project: python] >> [Project Interpreter] >> [Install按鈕]

 

 

由於Python統一了資料庫連線的介面,所以 pymysql 和 MySQLdb 在使用方式上是類似的:

複製程式碼
#建立資料庫連線
pymysql.Connect()引數說明 host(str): MySQL伺服器地址 port(int): MySQL伺服器埠號 user(str): 使用者名稱 passwd(str): 密碼 db(str): 資料庫名稱 charset(str): 連線編碼,存在中文的時候,連線需要新增charset='utf8',否則中文顯示亂碼。 connection物件支援的方法 cursor() 使用該連線建立並返回遊標 commit() 提交當前事務,不然無法儲存新建或者修改的資料 rollback() 回滾當前事務 close() 關閉連線 cursor物件支援的方法 execute(op) 執行SQL,並返回受影響行數 fetchone() 取得結果集的下一行 fetchmany(size) 獲取結果集的下幾行 fetchall() 獲取結果集中的所有行 rowcount() 返回資料條數或影響行數 close() 關閉遊標物件
複製程式碼

 

==================MySQL===================

 

首先在連線資料庫之前,先建立一個交易表,方便測試 pymysql 的功能:

 

複製程式碼
DROP TABLE IF EXISTS trade;

CREATE TABLE trade (
  id int(4) unsigned NOT NULL AUTO_INCREMENT,
  name varchar(6) NOT NULL COMMENT '使用者真實姓名',
  account varchar(15) NOT NULL COMMENT '銀行儲蓄賬號',
  saving decimal(8,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '賬戶儲蓄金額',
  expend decimal(8,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '賬戶支出總計',
  income decimal(8,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '賬戶收入總計',
  PRIMARY KEY (id),
  UNIQUE KEY name_UNIQUE (name)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO trade VALUES (1,'喬布斯','18012345678',0.00,0.00,0.00);
複製程式碼

 

==================Python===================

 

使用Python指令碼實現增刪改查和事務處理,原始碼如下:

 

複製程式碼
import pymysql.cursors

# 連線資料庫
connect = pymysql.Connect(
    host='localhost',
    port=3310,
    user='woider',
    passwd='3243',
    db='python',
    charset='utf8'
)

# 獲取遊標
cursor = connect.cursor()

# 插入資料
sql = "INSERT INTO trade (name, account, saving) VALUES ( '%s', '%s', %.2f )"
data = ('雷軍', '13512345678', 10000)
cursor.execute(sql % data)
connect.commit()
print('成功插入', cursor.rowcount, '條資料')

# 修改資料
sql = "UPDATE trade SET saving = %.2f WHERE account = '%s' "
data = (8888, '13512345678')
cursor.execute(sql % data)
connect.commit()
print('成功修改', cursor.rowcount, '條資料')

# 查詢資料
sql = "SELECT name,saving FROM trade WHERE account = '%s' "
data = ('13512345678',)
cursor.execute(sql % data)
for row in cursor.fetchall():
    print("Name:%s\tSaving:%.2f" % row)
print('共查找出', cursor.rowcount, '條資料')

# 刪除資料
sql = "DELETE FROM trade WHERE account = '%s' LIMIT %d"
data = ('13512345678', 1)
cursor.execute(sql % data)
connect.commit()
print('成功刪除', cursor.rowcount, '條資料')

# 事務處理
sql_1 = "UPDATE trade SET saving = saving + 1000 WHERE account = '18012345678' "
sql_2 = "UPDATE trade SET expend = expend + 1000 WHERE account = '18012345678' "
sql_3 = "UPDATE trade SET income = income + 2000 WHERE account = '18012345678' "

try:
    cursor.execute(sql_1)  # 儲蓄增加1000
    cursor.execute(sql_2)  # 支出增加1000
    cursor.execute(sql_3)  # 收入增加2000
except Exception as e:
    connect.rollback()  # 事務回滾
    print('事務處理失敗', e)
else:
    connect.commit()  # 事務提交
    print('事務處理成功', cursor.rowcount)

# 關閉連線
cursor.close()
connect.close()
複製程式碼

 

==================測試結果===================