mysql五:pymysql模塊

1、介紹

  以前都是經過MySQ自帶的命令行客戶端工具Mysql來操做數據庫,那如何在Python程序中操做數據庫呢?這就須要用到pymysql模塊了。mysql

  這個模塊本質就是一個套接字客戶端軟件,使用前須要實現安裝sql

pip3 install pymysql

2、連接、執行sql、關閉遊標

  經過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
登陸成功
"""

3、execute()之sql注入

  注意:符號--會註釋掉它以後的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=""
# 登陸成功
sql注入案例

  根本原理:就根據程序的字符串拼接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>>:
登陸失敗
"""
代碼改造爲防止sql注入

4、增、刪、改:conn.commit()

   增、刪、改的操做類似。以對錶格添加記錄爲例。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  |
+----+--------+------+
"""

5、查:fetchone,fetchmany,fetchall

# 創建連接
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  |
+----+--------+------+
"""

6、獲取插入的最後一條數據的自增ID

# -*- 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  |
+----+--------+------+
"""
相關文章
相關標籤/搜索