pymysql模塊的使用

  pymysql就是用來在python程序中如何操做mysql,他與mysql自帶的那個客戶端、Navicat是同樣的,本質上就是一個套接字客戶端,只不過這個套接字客戶端是在python程序中用的。

  1、鏈接mysql,執行mysql語句,關閉

import pymysql
user=input('用戶名: ').strip()
pwd=input('密碼: ').strip()
#連接,指定ip地址和端口,本機上測試時ip地址能夠寫localhost或者本身的ip地址或者127.0.0.1,而後你操做數據庫的時候的用戶名,密碼,要指定你操做的是哪一個數據庫,指定庫名,還要指定字符集。否則會出現亂碼
conn=pymysql.connect(host='localhost',port=3306,user='root',password='123',database='student',charset='utf8') #指定編碼爲utf8的時候,注意沒有-,別寫utf-8,
#獲得conn這個鏈接對象
#遊標
cursor=conn.cursor() #這就想到於mysql自帶的那個客戶端的遊標mysql> 在這後面輸入指令,回車執行
#cursor=conn.cursor(cursor=pymysql.cursors.DictCursor) #獲取字典數據類型表示的結果:{'sid': 1, 'gender': '男', 'class_id': 1, 'sname': '理解'} {'字段名':值}
#而後給遊標輸入sql語句並執行sql語句execute
sql='select * from userinfo where name="%s" and password="%s"' %(user,pwd) #注意%s須要加引號,執行這句sql的前提是醫藥有個userinfo表,裏面有name和password兩個字段,還有一些數據,本身添加數據昂
res=cursor.execute(sql) #執行sql語句,返回sql查詢成功的記錄數目,是個數字,是受sql語句影響到的記錄行數,其實除了受影響的記錄的條數以外,這些記錄的數據也都返回了給遊標,這個就至關於咱們subprocess模塊裏面的管道PIPE,乘放着返回的數據
#all_data=cursor.fetchall()  #獲取返回的全部數據,注意凡是取數據,取過的數據就沒有了,結果都是元祖格式的
#many_data=cursor.fetchmany(3) #一下取出3條數據,
#one_data=cursor.fetchone()  #按照數據的順序,一次只拿一個數據,下次再去就從第二個取了,由於第一個被取出去了,取一次就沒有了,結果也都是元祖格式的
  fetchone:(1, '', 1, '理解')
  fetchone:(2, '', 1, '鋼蛋')
  fetchall:((3, '', 1, '張三'), (4, '', 1, '張一'))
#上面fetch的結果都是元祖格式的,無法看出哪一個數據是對應的哪一個字段,這樣是否是不太好看,想想,咱們能夠經過python的哪種數據類型,能把字段和對應的數據表示出來最清晰,固然是字典{'字段名':值}
#咱們能夠再建立遊標的時候,在cursor裏面加上一個參數:cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)獲取的結果就是字典格式的,fetchall或者fetchmany取出的結果是列表套字典的數據形式
上面咱們說,咱們的數據取一次是否是就沒有了啊,實際上不是的,這個取數據的操做就像讀取文件內容同樣,每次read以後,光標就移動到了對應的位置,咱們能夠經過seek來移動光標
一樣,咱們能夠移動遊標的位置,繼續取咱們前面的數據,經過cursor.scroll(數字,模式),第一個參數就是一個int類型的數字,表示日後移動的記錄條數,第二個參數爲移動的模式,有兩個值:absolute:絕對移動,relative:相對移動
#絕對移動:它是相對於全部數據的起始位置開始日後面移動的
#相對移動:他是相對於遊標的當前位置開始日後移動的
#絕對移動的演示
#print(cursor.fetchall())
#cursor.scroll(3,'absolute') #從初始位置日後移動三條,那麼下次取出的數據爲第四條數據
#print(cursor.fetchone())
#相對移動的演示
#print(cursor.fetchone())
#cursor.scroll(1,'relative') #經過上面取了一次數據,遊標的位置在第二條的開頭,我如今相對移動了1個記錄,那麼下次再取,取出的是第三條,我相對於上一條,往下移動了一條
#print(cursor.fetchone())
cursor.close() #關閉遊標
conn.close()   #關閉鏈接

  2、execute()sql注入

#咱們來使用數據來進行一下用戶名和密碼的認證操做
import pymysql

conn = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    password='666',
    database='crm',
    charset='utf8'
)

cursor = conn.cursor(pymysql.cursors.DictCursor)
uname = input('請輸入用戶名:')
pword = input('請輸入密碼:')

sql = "select * from userinfo where username='%s' and password='%s';"%(uname,pword)

res = cursor.execute(sql) #res咱們說是獲得的行數,若是這個行數不爲零,說明用戶輸入的用戶名和密碼存在,若是爲0說名存在,你想一想對不

print(res) #若是輸入的用戶名和密碼錯誤,這個結果爲0,若是正確,這個結果爲1
if res:
    print('登錄成功')
else:
    print('用戶名和密碼錯誤!')

#經過上面的驗證方式,比咱們使用文件來保存用戶名和密碼信息的來進行驗證操做要方便不少。

  但其實咱們就算不知道帳戶和密碼也能夠登陸成功。python

uname = input('請輸入用戶名:')
pword = input('請輸入密碼:')

sql = "select * from userinfo where username='%s' and password='%s';"%(uname,pword)
print(sql)
res = cursor.execute(sql) #res咱們說是獲得的行數,若是這個行數不爲零,說明用戶輸入的用戶名和密碼存在,若是爲0說名存在,你想一想對不

print(res) #若是輸入的用戶名和密碼錯誤,這個結果爲0,若是正確,這個結果爲1
if res:
    print('登錄成功')
else:
    print('用戶名和密碼錯誤!')
#運行看結果:竟然登錄成功
請輸入用戶名:chao' -- xxx
請輸入密碼:
select * from userinfo where username='chao' -- xxx' and password='';
登錄成功

咱們來分析一下:
此時uname這個變量等於什麼,等於chao' -- xxx,而後咱們來看咱們的sql語句被這個字符串替換以後是個什麼樣子:
select * from userinfo where username='chao' -- xxx' and password=''; 其中chao後面的這個',在進行字符串替換的時候,咱們輸入的是chao',這個引號和前面的引號組成了一對,而後後面--在sql語句裏面是註釋的意思,也就是說--後面的sql語句被註釋掉了。
也就是說,拿到的sql語句是select * from userinfo where username=
'chao';而後就去本身的數據庫裏面去執行了,發現可以找到對應的記錄,由於有用戶名爲chao的記錄,而後他就登錄成功了,可是其實他連密碼都不知道,只知道個用戶名。。。,他完美的跳過了你的認證環節。

不用知道帳戶和密碼mysql

請輸入用戶名:xxx' or 1=1 -- xxxxxx
請輸入密碼:
select * from userinfo where username='xxx' or 1=1 -- xxxxxx' and password='';
登錄成功sql

咱們只輸入了一個xxx' 加or 加 1=1 加 -- 加任意字符串
看上面被執行的sql語句你就發現了,or 後面跟了一個永遠爲真的條件,那麼即使是username對不上,可是or後面的條件是成立的,也可以登錄成功。數據庫

  對於上面的mysql注入問題,其實咱們能夠經過execute()就能夠解決。函數

uname = input('請輸入用戶名:') #輸入的內容是:chao' -- xxx或者xxx' or 1=1 -- xxxxx
pword = input('請輸入密碼:')

sql = "select * from userinfo where username=%s and password=%s;"
print(sql)
res = cursor.execute(sql,[uname,pword]) #res咱們說是獲得的行數,若是這個行數不爲零,說明用戶輸入的用戶名和密碼存在,若是爲0說名存在,你想一想對不

print(res) #若是輸入的用戶名和密碼錯誤,這個結果爲0,若是正確,這個結果爲1
if res:
    print('登錄成功')
else:
    print('用戶名和密碼錯誤!')
#看結果:
請輸入用戶名:xxx' or 1=1 -- xxxxx
請輸入密碼:
select * from userinfo where username=%s and password=%s;
0
用戶名和密碼錯誤!
#cursor.execute(sql,[uname,pword]) ,其實它本質也是幫你進行了字符串的替換,只不過它會將uname和pword裏面的特殊字符給過濾掉

  3、增刪改:conn.commit()

import pymysql
#連接
conn=pymysql.connect(host='localhost',port='3306',user='root',password='123',database='crm',charset='utf8')
#遊標
cursor=conn.cursor()

#執行sql語句
#part1
# sql='insert into userinfo(name,password) values("root","123456");'
# res=cursor.execute(sql) #執行sql語句,返回sql影響成功的行數
# print(res)
# print(cursor.lastrowid) #返回的是你插入的這條記錄是到了第幾條了

#part2
# sql='insert into userinfo(name,password) values(%s,%s);'
# res=cursor.execute(sql,("root","123456")) #執行sql語句,返回sql影響成功的行數
# print(res)
#還能夠進行更改操做:
#res=cursor.excute("update userinfo set username='taibaisb' where id=2")
#print(res) #結果爲1
#part3
sql='insert into userinfo(name,password) values(%s,%s);'
res=cursor.executemany(sql,[("root","123456"),("lhf","12356"),("eee","156")]) #執行sql語句,返回sql影響成功的行數,一次插多條記錄
print(res)
#上面的幾步,雖然都有返回結果,也就是那個受影響的函數res,可是你去數據庫裏面一看,並無保存到數據庫裏面,
conn.commit() #必須執行conn.commit,注意是conn,不是cursor,執行這句提交後才發現表中插入記錄成功,沒有這句,上面的這幾步操做其實都沒有成功保存。
cursor.close()
conn.close()

  4、查:fetchone,fetchmany,fetchall

import pymysql
#連接
conn=pymysql.connect(host='localhost',user='root',password='123',database='egon')
#遊標
cursor=conn.cursor()

#執行sql語句
sql='select * from userinfo;'
rows=cursor.execute(sql) #執行sql語句,返回sql影響成功的行數rows,將結果放入一個集合,等待被查詢

# cursor.scroll(3,mode='absolute') # 相對絕對位置移動
# cursor.scroll(3,mode='relative') # 相對當前位置移動
res1=cursor.fetchone()
res2=cursor.fetchone()
res3=cursor.fetchone()
res4=cursor.fetchmany(2)
res5=cursor.fetchall()
print(res1)
print(res2)
print(res3)
print(res4)
print(res5)
print('%s rows in set (0.00 sec)' %rows)
conn.commit()
#提交後才發現表中插入記錄成功 cursor.close() conn.close() ''' (1, 'root', '123456') (2, 'root', '123456') (3, 'root', '123456') ((4, 'root', '123456'), (5, 'root', '123456')) ((6, 'root', '123456'), (7, 'lhf', '12356'), (8, 'eee', '156')) rows in set (0.00 sec) '''

  5、得到插入的最後一條數據的自增id

import pymysql
conn=pymysql.connect(host='localhost',user='root',password='123',database='egon')
cursor=conn.cursor()

sql='insert into userinfo(name,password) values("xxx","123");'
rows=cursor.execute(sql)
print(cursor.lastrowid) #在插入語句後查看

conn.commit()

cursor.close()
conn.close()
相關文章
相關標籤/搜索