以前都是經過MySQ自帶的命令行客戶端工具Mysql來操做數據庫,那如何在Python程序中操做數據庫呢?這就須要用到pymysql模塊了。mysql
這個模塊本質就是一個套接字客戶端軟件,使用前須要實現安裝sql
pip3 install pymysql
經過Navicat建立一個db9數據庫並建立userinfo表數據庫
mysql> desc userinfo; +-------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | user | char(16) | NO | | NULL | | | pwd | char(20) | YES | | NULL | | +-------+----------+------+-----+---------+----------------+ mysql> select * from userinfo; +----+------+------+ | id | user | pwd | +----+------+------+ | 1 | egon | 123 | | 2 | alex | 456 | +----+------+------+ """ """ # 登陸數據庫,容許遠程訪問 mysql> grant all on *.* to 'root'@'%' identified by '1234'; Query OK, 0 rows affected, 1 warning (0.01 sec) # 當即刷新數據庫,配置當即生效 mysql> flush privileges; Query OK, 0 rows affected (0.01 sec)
mysql模塊的基本使用:ide
# -*- coding:utf-8 -*- __author__ = 'Qiushi Huang' import pymysql # 套接字 user = input('user>>:').strip() pwd = input('pwd>>:').strip() # 創建連接 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='1234', db='db9', charset='utf8' # mysql指定utf-8的格式是沒有槓的 ) # 拿到遊標 course=conn.cursor() # 執行完畢返回的結果集默認以元組顯示 # 執行sql語句 sql = 'select * from userinfo where user = "%s" and pwd="%s"' % (user, pwd) rows = course.execute(sql) # 遊標的execute接口傳入sql語句,返回sql查詢成功的記錄數 # 資源回收 course.close() # 關閉遊標 conn.close() # 關閉鏈接 # 進行判斷 if rows: print('登陸成功') else: print('登陸失敗') """ user>>:egon pwd>>:123 登陸成功 """
注意:符號--會註釋掉它以後的sql,正確的語法:--後至少有一個任意字符函數
# -*- coding:utf-8 -*- __author__ = 'Qiushi Huang' # pip3 install pymysql import pymysql # 套接字 user = input('user>>:').strip() pwd = input('pwd>>:').strip() # 創建連接 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='1234', db='db9', charset='utf8' # mysql指定utf-8的格式是沒有槓的 ) # 拿到遊標 course=conn.cursor() # 執行完畢返回的結果集默認以元組顯示 # 執行sql語句 sql = 'select * from userinfo where user = "%s" and pwd="%s"' % (user, pwd) print(sql) # 查看被注入的sql rows = course.execute(sql) # 遊標的execute接口傳入sql語句,返回sql查詢成功的記錄數 # 資源回收 course.close() # 關閉遊標 conn.close() # 關閉鏈接 # 進行判斷 if rows: print('登陸成功') else: print('登陸失敗') """ user>>:egon" -- xxxx # 雙"-"以後全都變爲註釋 pwd>>:123 select * from userinfo where user = "egon" -- xxxx" and pwd="123" 登陸成功 """ # 不用輸入密碼直接登陸,"和sql語句中的"拼接 , 或判斷與1=1 # user>>:xxx" or 1=1 -- hahahwdda" and pwd="" # pwd>>: # select * from userinfo where user = "xxx" or 1=1 -- hahahwdda and pwd=""" and pwd="" # 登陸成功
根本原理:就根據程序的字符串拼接name='%s',咱們輸入一個xxx' -- haha,用咱們輸入的xxx加'在程序中拼接成一個判斷條件name='xxx' -- haha'工具
解決辦法:學習
# 原來是咱們對sql進行字符串拼接 # sql="select * from userinfo where name='%s' and password='%s'" %(user,pwd) # print(sql) # res=cursor.execute(sql) #改寫爲(execute幫咱們作字符串拼接,咱們無需且必定不能再爲%s加引號了) sql="select * from userinfo where name=%s and password=%s" #!!!注意%s須要去掉引號,由於pymysql會自動爲咱們加上 res=cursor.execute(sql,[user,pwd]) #pymysql模塊自動幫咱們解決sql注入的問題,只要咱們按照pymysql的規矩來。
# -*- coding:utf-8 -*- __author__ = 'Qiushi Huang' # pip3 install pymysql import pymysql # 套接字 user = input('user>>:').strip() pwd = input('pwd>>:').strip() # 創建連接 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='1234', db='db9', charset='utf8' # mysql指定utf-8的格式是沒有槓的 ) # 拿到遊標 course=conn.cursor() # 執行完畢返回的結果集默認以元組顯示 # 執行sql語句 # sql = 'select * from userinfo where user = "%s" and pwd="%s"' % (user, pwd) # print(sql) # 查看被注入的sql sql = 'select * from userinfo where user = %s and pwd=%s' rows = course.execute(sql, (user, pwd)) # 不使用字符串拼接,採用execute在後面傳值的方式 # 資源回收 course.close() # 關閉遊標 conn.close() # 關閉鏈接 # 進行判斷 if rows: print('登陸成功') else: print('登陸失敗') """ user>>:xxx" or 1=1 -- hahahwdda" and pwd="" pwd>>: 登陸失敗 """
增、刪、改的操做類似。以對錶格添加記錄爲例。fetch
# -*- coding:utf-8 -*- __author__ = 'Qiushi Huang' import pymysql # 創建連接 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='1234', db='db9', charset='utf8' # mysql指定utf-8的格式是沒有槓的 ) # 拿遊標 cursor=conn.cursor() # 執行sql # 增刪改 sql='insert into userinfo(user,pwd) values(%s,%s);' # 單一操做 # res=cursor.execute(sql,("wxx","123")) #執行sql語句,返回sql影響成功的行數 # print(res) # 批量操做 cursor.executemany(sql,[('yxx','123'), ('egon1','123'), ('zurong','123')]) conn.commit() # 注意:提交後記錄纔會插入成功 # 關閉連接 cursor.close() conn.close() """ +----+--------+------+ | id | user | pwd | +----+--------+------+ | 1 | egon | 123 | | 2 | alex | 456 | | 3 | hqs | 123 | | 5 | wxx | 123 | | 8 | yxx | 123 | | 9 | egon1 | 123 | | 10 | zurong | 123 | +----+--------+------+ """
# 創建連接 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='1234', db='db9', charset='utf8' # mysql指定utf-8的格式是沒有槓的 ) # 拿遊標 cursor=conn.cursor() # 執行sql查詢 rows = cursor.execute('select * from userinfo;') # 把sql發給服務端 # print(rows) # 顯示的僅僅是受影響的行數 # 爲了獲得執行結果,須要使用fetchone()函數,一次獲得一條服務端執行記錄 print(cursor.fetchone()) print(cursor.fetchone()) """ (1, 'egon', '123') (2, 'alex', '456') """ conn.commit() # 注意:提交後記錄纔會插入成功 # 關閉連接 cursor.close() conn.close()
能夠看到上面的記錄沒有字段信息,很難分辨數據具體屬於哪一個字段。所以須要在拿遊標時,使用:cursor=conn.cursor(pymysql.cursors.DictCursor) 獲得基於字典的遊標。spa
conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='1234', db='db9', charset='utf8' # mysql指定utf-8的格式是沒有槓的 ) # 拿遊標 cursor=conn.cursor(pymysql.cursors.DictCursor) # 基於字典的遊標 # 執行sql查詢 rows = cursor.execute('select * from userinfo;') # print(cursor.fetchone()) # print(cursor.fetchone()) """ {'id': 1, 'user': 'egon', 'pwd': '123'} {'id': 2, 'user': 'alex', 'pwd': '456'} """ # 一次取多個 print(cursor.fetchmany(3)) """ [{'id': 1, 'user': 'egon', 'pwd': '123'}, {'id': 2, 'user': 'alex', 'pwd': '456'}, {'id': 3, 'user': 'hqs', 'pwd': '123'}] """ # 所有取出 print(cursor.fetchall()) # 若是是和上面的和語句一塊兒執行,則是取出id=3以後的數據 print(cursor.fetchall()) # 上一條取完全部數據,遊標已經到了記錄結尾,這次爲空 """ [{'id': 1, 'user': 'egon', 'pwd': '123'}, {'id': 2, 'user': 'alex', 'pwd': '456'}, {'id': 3, 'user': 'hqs', 'pwd': '123'}] [{'id': 5, 'user': 'wxx', 'pwd': '123'}, {'id': 8, 'user': 'yxx', 'pwd': '123'}, {'id': 9, 'user': 'egon1', 'pwd': '123'}, {'id': 10, 'user': 'zurong', 'pwd': '123'}] [] """ conn.commit() # 注意:提交後記錄纔會插入成功 # 關閉連接 cursor.close() conn.close()
從上例中能夠學習到fetchone,fetchmany,fetchall這三種方法的使用和區別。可是由此也看到,讀取記錄存在遊標位置問題。命令行
相對絕對位置移動:cursor.scroll(3,mode='absolute')
相對當前位置移動:cursor.scroll(3,mode='relative')
conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='1234', db='db9', charset='utf8' # mysql指定utf-8的格式是沒有槓的 ) # 拿遊標 cursor=conn.cursor(pymysql.cursors.DictCursor) # 基於字典的遊標 # 執行sql查詢 rows = cursor.execute('select * from userinfo;') print(cursor.fetchall()) # 先移動到最後 # 遊標移動——相對絕對位置移動 cursor.scroll(2,mode='absolute') # 相對絕對位置移動——從結果最開始起到第2條數據結尾 print(cursor.fetchone()) print(cursor.fetchone()) """ [{'id': 1, 'user': 'egon', 'pwd': '123'}, ...] {'id': 3, 'user': 'hqs', 'pwd': '123'} {'id': 5, 'user': 'wxx', 'pwd': '123'} """ # 遊標移動——相對當前位置移動 cursor.scroll(2,mode='relative') # 相對當前位置移動——從id=5這個結果開始,移動到id=9最後 print(cursor.fetchone()) print(cursor.fetchone()) """ {'id': 10, 'user': 'zurong', 'pwd': '123'} None # 沒有數據了還查詢,即返回None """ conn.commit() # 注意:提交後記錄纔會插入成功 # 關閉連接 cursor.close() conn.close() """ +----+--------+------+ | id | user | pwd | +----+--------+------+ | 1 | egon | 123 | | 2 | alex | 456 | | 3 | hqs | 123 | | 5 | wxx | 123 | | 8 | yxx | 123 | | 9 | egon1 | 123 | | 10 | zurong | 123 | +----+--------+------+ """
# -*- coding:utf-8 -*- __author__ = 'Qiushi Huang' import pymysql # conn=pymysql.connect(host='127.0.0.1',user='root',password='1234',database='egon') conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='1234', db='db9', charset='utf8' # mysql指定utf-8的格式是沒有槓的 ) cursor=conn.cursor() sql='insert into userinfo(user,pwd) values("xxx","123");' rows=cursor.execute(sql) print(cursor.lastrowid) # 插入以前id走到的數字(下一條即將插入的記錄的id) conn.commit() cursor.close() conn.close() """ 11 +----+--------+------+ | id | user | pwd | +----+--------+------+ | 1 | egon | 123 | | 2 | alex | 456 | | 3 | hqs | 123 | | 5 | wxx | 123 | | 8 | yxx | 123 | | 9 | egon1 | 123 | | 10 | zurong | 123 | +----+--------+------+ """