今日內容:python
1.navicat mysql
2.pymysqlsql
1.navicat 數據庫
須要掌握ide
#1. 測試+連接數據庫 #2. 新建庫 #3. 新建表,新增字段+類型+約束 #4. 設計表:外鍵 #5. 新建查詢 #6. 備份庫/表 #注意: 批量加註釋:ctrl+?鍵 批量去註釋:ctrl+shift+?鍵
2.pymysql函數
咱們要學的pymysql是用python程序如何操做mysql,本質上就是一個套接字客戶端,只不過這個套接字客戶端是在python程序中的.測試
#安裝 pip3 install pymysql
鏈接,執行sql ,關閉遊標fetch
import pymysql user=input('請輸入用戶名:') upwd=input('請輸入密碼:') conn=pymysql.connect( host='localhost', port=3306, user='root', password='xxx',#密碼爲字符串類型 database='xxx', charset='utf8') #建立遊標 cur=conn.cursor() #寫指令 sql=input('請輸入你的指令:') #執行sql指令 res=cur.execute(sql) #注:這裏拿到的res是獲得的指令的條數 #若是想要拿數據,用fetchall() all_data=cur.fetchall() #此時返回的是全部的數據,但凡是數據,和讀文件差很少,
都是光標的位置在哪就開始讀哪. many_data=cur.fetchmay(4)#取出4條數據 #上面的fetch的結果都是元組類型的,無法看出哪一個數據對應哪一個字段,因此咱們能夠用字典,{'字段名':值} cursor=conn.cursor(currsor=pymysql.cursors.DictCursor) #此時獲取的結果就是字典格式, #移動光標 currsor.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()) print(res) #一個數字 cursor.close() #關閉遊標 conn.close() #關閉鏈接
execute()之sql注入es5
咱們來使用數據進行用戶名和密碼的認證操做spa
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('用戶名和密碼錯誤!') #經過上面的驗證方式,比咱們使用文件來保存用戶名和密碼信息的來進行驗證操做要方便不少。
可是上面的操做是有BUG的,若是將在輸入用戶名的地方輸入一個 chao'空格而後--空格而後加上任意的字符串,就可以登錄成功,也就是隻知道用戶名的狀況下,他就能登錄成功的狀況:
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=''; 1 登錄成功 咱們來分析一下: 此時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的記錄,
而後他就登錄成功了,可是其實他連密碼都不知道,只知道個用戶名。。。,他完美的跳過了你的認證環節。
正確的解決方案
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 用戶名和密碼錯誤
剛纔問題的緣由在於:
#一、sql注入之:用戶存在,繞過密碼 chao' -- 任意字符 #二、sql注入之:用戶不存在,繞過用戶與密碼 xxx' or 1=1 -- 任意字符
解決方案的總結:
# 原來是咱們對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的規矩來。
增 刪 改:conn.commit()
注意:sql語句不要本身拼接,要交給excute來拼接
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()
查: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()
獲取插入的最後一條數據的自增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()