Python全棧之學(xué)習(xí)MySQL(3)
1. pymysql的基本操作
# ### python 操作mysql import pymysql # ### 1.基本語(yǔ)法 """ # (1) 創(chuàng)建連接對(duì)象 host user password database 這四個(gè)參數(shù)必寫 conn = pymysql.connect( host="127.0.0.1" , user="root" , password="123456" , database="db003" , charset="utf8" , port=3306 ) # (2) 創(chuàng)建游標(biāo)對(duì)象 (用來(lái)操作數(shù)據(jù)庫(kù)的增刪改查) cursor = conn.cursor() print(cursor) # (3) 執(zhí)行sql語(yǔ)句 sql = "select * from employee" # 執(zhí)行查詢語(yǔ)句返回的總條數(shù) res = cursor.execute(sql) print(res) # (4) 獲取數(shù)據(jù) fetchone 獲取一條數(shù)據(jù) # 返回的是元組,里面包含的是第一條的完整數(shù)據(jù) res = cursor.fetchone() print(res) res = cursor.fetchone() print(res) res = cursor.fetchone() print(res) # (5) 釋放游標(biāo)對(duì)象 cursor.close() # (6) 釋放連接對(duì)象 conn.close() """ # ### 2.創(chuàng)建/刪除 表操作 # conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db003") # cursor = conn.cursor() # 1.創(chuàng)建一張表 sql = """ create table t1( id int unsigned primary key auto_increment, first_name varchar(255) not null, last_name varchar(255) not null, sex tinyint not null, age tinyint unsigned not null, money float ); """ # res = cursor.execute(sql) # print(res) # 無(wú)意義返回值 # 2.查詢表結(jié)構(gòu) """ sql = "desc t1" res = cursor.execute(sql) print(res) # 返回的是字段的個(gè)數(shù) res = cursor.fetchone() print(res) res = cursor.fetchone() print(res) res = cursor.fetchone() print(res) """ # 3.刪除表 """ try: sql = "drop table t1" res = cursor.execute(sql) print(res) # 無(wú)意義返回值 except: pass """ # ### 3.事務(wù)處理 """pymysql 默認(rèn)開(kāi)啟事務(wù)的,所有增刪改的數(shù)據(jù)必須提交,否則默認(rèn)回滾;rollback""" conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db003") cursor = conn.cursor() sql1 = "begin" sql2 = "update employee set emp_name='程咬鉆石' where id = 18 " sql3 = "commit" res1 = cursor.execute(sql1) res1 = cursor.execute(sql2) res1 = cursor.execute(sql3) # 一般在查詢的時(shí)候,通過(guò)fetchone來(lái)獲取結(jié)果 res1 = cursor.fetchone() print(res1) cursor.close() conn.close()
2. sql注入攻擊
# ### sql 注入攻擊
import pymysql
# (1) sql注入的現(xiàn)象
''' 現(xiàn)象:繞開(kāi)賬號(hào)密碼登錄成功 '''
'''
user = input("請(qǐng)輸入您的用戶名>>>")
pwd = input("請(qǐng)輸入您的密碼>>>")
conn = pymysql.connect(host="127.0.0.1" , user="root" , password="123456",database="db005")
cursor = conn.cursor()
sql1 = """
create table usr_pwd(
id int unsigned primary key auto_increment,
username varchar(255) not null,
password varchar(255) not null
)
"""
sql2 = "select * from usr_pwd where username='%s' and password='%s' " % (user,pwd)
print(sql2)
res = cursor.execute(sql2)
print(res) # 1查到成功 0沒(méi)查到失敗
# res=cursor.fetchone()
"""
select * from usr_pwd where username='2222' or 4=4 -- aaa' and password=''
相當(dāng)于 : select * from usr_pwd where 10=10; 繞開(kāi)了賬戶和密碼的判斷 -- 代表的是注釋;
"""
if res:
print("登錄成功")
else:
print("登錄失敗")
cursor.close()
conn.close()
'''
# (2) 預(yù)處理機(jī)制
""" 在執(zhí)行sql語(yǔ)句之前,提前對(duì)sql語(yǔ)句中出現(xiàn)的字符進(jìn)行過(guò)濾優(yōu)化,避免sql注入攻擊 """
""" execute( sql , (參數(shù)1,參數(shù)2,參數(shù)3 .... ) ) execute2個(gè)參數(shù)默認(rèn)開(kāi)啟預(yù)處理機(jī)制 """
""" 填寫 234234' or 100=100 -- sdfsdfsdfsdf 嘗試攻擊 """
user = input("請(qǐng)輸入您的用戶名>>>")
pwd = input("請(qǐng)輸入您的密碼>>>")
conn = pymysql.connect(host="127.0.0.1" , user="root" , password="123456",database="db005")
cursor = conn.cursor()
sql = "select * from usr_pwd where username=%s and password=%s"
res = cursor.execute(sql , (user,pwd) )
print(res)
print( "登錄成功" if res else "登錄失敗" )
cursor.close()
conn.close()
3. sql增刪改查
# ### python 操作mysql 數(shù)據(jù)庫(kù) (增刪改查)
import pymysql
"""
python 操作mysql增刪改時(shí),默認(rèn)是開(kāi)啟事務(wù)的,
必須最后commit提交數(shù)據(jù),才能產(chǎn)生變化
提交數(shù)據(jù): commit
默認(rèn)回滾: rollback
"""
conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db005")
# 默認(rèn)獲取查詢結(jié)果時(shí)是元組,可以設(shè)置返回字典; cursor=pymysql.cursors.DictCursor
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 執(zhí)行對(duì)mysql 的操作
# 1.增
"""
sql = "insert into t1(first_name,last_name,sex,age,money) values(%s,%s,%s,%s,%s)"
# (1) 一次插入一條
res = cursor.execute( sql , ("孫","健",0,15,20000) )
print(res) # 1
# 獲取最后插入這條數(shù)據(jù)的id號(hào)
print(cursor.lastrowid)
# (2) 一次插入多條
res = cursor.executemany( sql , [ ("安","曉東",0,18,30000) , ("劉","玉波",1,20,50000) ,("張","光旭",0,80,60000) , ("李","是元",0,10,10) , ("高","大奧",1,20,80000) ] )
print(res) # 返回插入的條數(shù)
# 插入5條數(shù)據(jù)中的第一條數(shù)據(jù)的id
print(cursor.lastrowid)
# 獲取最后一個(gè)數(shù)據(jù)的id
sql = "select id from t1 order by id desc limit 1"
res = cursor.execute(sql)
print(res)
# 獲取結(jié)果,返回元組
res = cursor.fetchone()
print(res["id"])
# 默認(rèn)元組 : (57, '高', '大奧', 1, 20, 80000.0)
# 返回字典 : {'id': 51, 'first_name': '高', 'last_name': '大奧', 'sex': 1, 'age': 20, 'money': 80000.0}
"""
# 2.刪
"""
sql = "delete from t1 where id in (%s,%s,%s)"
res = cursor.execute(sql , (3,4,5) )
print(res) # 返回的是3,代表刪除了3條
if res:
print("刪除成功")
else:
print("刪除失敗")
"""
# 3.改
"""
sql = "update t1 set first_name = '王' where id = %s"
sql = "update t1 set first_name = '王' where id in (%s,%s,%s,%s)"
res = cursor.execute(sql , (6,7,8,9))
print(res) # 返回的是4,代表修改了4條
if res:
print("修改成功")
else:
print("修改失敗")
"""
# 4.查
"""
fetchone 獲取一條
fetchmany 獲取多條
fetchall 獲取所有
"""
sql = "select * from t1"
res = cursor.execute(sql)
print(res) # 針對(duì)于查詢語(yǔ)句來(lái)說(shuō),返回的res是總條數(shù);
# (1) fetchone 獲取一條
res = cursor.fetchone()
print(res)
res = cursor.fetchone()
print(res)
# (2) fetchmany 獲取多條
res = cursor.fetchmany() # 默認(rèn)獲取的是一條數(shù)據(jù),返回列表,里面里面是一組一組的字典;
data = cursor.fetchmany(3)
print(data)
"""
[
{'id': 9, 'first_name': '王', 'last_name': '是元', 'sex': 0, 'age': 10, 'money': 10.0},
{'id': 10, 'first_name': '孫', 'last_name': '健', 'sex': 0, 'age': 15, 'money': 20000.0},
{'id': 11, 'first_name': '安', 'last_name': '曉東', 'sex': 0, 'age': 18, 'money': 30000.0}
]
"""
for row in data:
first_name = row["first_name"]
last_name = row["last_name"]
sex = row["sex"]
if sex == 0:
sex = "男性"
else:
sex = "女性"
age = row["age"]
money = row["money"]
strvar = "姓:{},名:{},性別:{},年齡:{},收入:{}".format(first_name,last_name,sex,age,money)
print(strvar)
# (3) fetchall 獲取所有
# data = cursor.fetchall()
# print(data)
# (4) 自定義搜索查詢的位置
print("<==================>")
# 1.相對(duì)滾動(dòng) relative
"""相對(duì)于上一次查詢的位置往前移動(dòng)(負(fù)數(shù)),或者往后移動(dòng)(正數(shù))"""
"""
cursor.scroll(-1,mode="relative")
# cursor.scroll(5,mode="relative")
res = cursor.fetchone()
print(res)
"""
# 2.絕對(duì)滾動(dòng) absolute
"""永遠(yuǎn)從數(shù)據(jù)的開(kāi)頭起始位置進(jìn)行移動(dòng),不能向前滾"""
cursor.scroll(0,mode="absolute")
res = cursor.fetchone()
print(res)
conn.commit()
cursor.close()
conn.close()
4. mysql的數(shù)據(jù)恢復(fù)
# ### (1) 導(dǎo)入導(dǎo)出 不要加分號(hào) 導(dǎo)出數(shù)據(jù)庫(kù) 1.退出mysql 2.選擇要導(dǎo)出的默認(rèn)路徑 3.mysqldump -uroot -p db001 > db001.sql mysqldump -uroot -p123456 db001 表1 表2 > ceshi01.sql 導(dǎo)入數(shù)據(jù)庫(kù) 1.登錄到mysql之后 2.創(chuàng)建新的數(shù)據(jù)庫(kù) # 注意:source db001.sql 后面沒(méi)有分號(hào)";" 3.source 路徑+文件 # ### (2) 如果服務(wù)器宕機(jī)了,有沒(méi)有備份數(shù)據(jù),如何恢復(fù)數(shù)據(jù) myisam: 直接新建一個(gè)數(shù)據(jù)庫(kù),然后把之前庫(kù)中的三個(gè)文件,粘貼復(fù)制到新的數(shù)據(jù)庫(kù)中,直接就恢復(fù)了 innodb: # innodb 在只有frm和ibd文件的情況下,如何恢復(fù)數(shù)據(jù); 安裝 MySQL Utilities https://downloads.mysql.com/archives/utilities/ cmd中找到frm那個(gè)文件,執(zhí)行如下命令: 切換到對(duì)應(yīng)目錄,執(zhí)行下面語(yǔ)句,不要加分號(hào) mysqlfrm --diagnostic ./文件目錄/t1.frm 查出建表語(yǔ)句,復(fù)制查詢出來(lái)的建表語(yǔ)句在mysql中創(chuàng)建的新數(shù)據(jù)中使用(新建一個(gè)數(shù)據(jù)庫(kù),然后執(zhí)行下面的建表語(yǔ)句) CREATE TABLE `innodb1` ( `id` int(11) DEFAULT NULL ) ENGINE=InnoDB; #對(duì)已創(chuàng)建的表進(jìn)行表空間卸載 刪除ibd文件 mysql> alter table innodb1 discard tablespace; 把要恢復(fù)的idb文件替換進(jìn)去 #對(duì)已創(chuàng)建的表進(jìn)行空間裝載 mysql> alter table innodb1 import tablespace; # ### (3) 配置linux下的編碼集 !includedir /etc/mysql/conf.d/ 客戶端的修改 # 設(shè)置mysql客戶端默認(rèn)字符集 default-character-set=utf8 !includedir /etc/mysql/mysql.conf.d/ 服務(wù)端的修改 # 服務(wù)端使用的字符集默認(rèn)為8比特編碼的latin1字符集 character-set-server=utf8 # 重啟數(shù)據(jù)庫(kù) service mysql restart
小總結(jié):
-- 是mysql的注釋 # 在sql注入那塊用到了 默認(rèn)python連接mysql的時(shí)候,都是開(kāi)啟了一個(gè)事務(wù),尤其是增刪改, 在改變數(shù)據(jù)的時(shí)候,一定要提交數(shù)據(jù),不提交數(shù)據(jù)(默認(rèn)回滾),不會(huì)真正的改變 \s 看一下服務(wù)器的數(shù)據(jù)
5. sql語(yǔ)句優(yōu)化
(1) 避免使用select *, (2) 不確定表大小時(shí)候,先用count(*)查下數(shù)據(jù). (3) 創(chuàng)建表時(shí)盡量使用 char 代替 varchar (4) 定長(zhǎng)的字段放前面,變長(zhǎng)的字段放后面.(盡可能小的改變樹狀結(jié)構(gòu)高度) (5) 組合索引代替多個(gè)單列索引 (由于mysql中每次只能使用一個(gè)索引,所以經(jīng)常使用多個(gè)條件查詢時(shí)更適 合使用組合索引) (6) 盡量使用短索引(小數(shù)據(jù)值) (7) 重復(fù)少的字段值不適合做索引,例:性別不適合 (8) 使用連接(JOIN)來(lái)代替子查詢(Sub-Queries)
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Python實(shí)現(xiàn)獲取sonarqube數(shù)據(jù)
sonarqube是一款代碼分析的工具,可以對(duì)通過(guò)soanrScanner掃描后的數(shù)據(jù)傳遞給sonarqube進(jìn)行分析,本文為大家整理了Python獲取sonarqube數(shù)據(jù)的方法,需要的可以參考下2023-05-05
Python OpenCV實(shí)現(xiàn)圖片上輸出中文
這篇文章主要為大家詳細(xì)介紹了Python OpenCV實(shí)現(xiàn)圖片上輸出中文,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
opencv之顏色過(guò)濾只留下圖片中的紅色區(qū)域操作
這篇文章主要介紹了opencv之顏色過(guò)濾只留下圖片中的紅色區(qū)域操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06
python中必會(huì)的四大高級(jí)數(shù)據(jù)類型(字符,元組,列表,字典)
這篇文章主要介紹了python中必會(huì)的四大高級(jí)數(shù)據(jù)類型(字符,元組,列表,字典),本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05
深入了解python基于tkinter寫的畫圖項(xiàng)目
這篇文章主要為大家介紹了python基于tkinter寫的畫圖項(xiàng)目,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-12-12
python3實(shí)現(xiàn)域名查詢和whois查詢功能
本篇文章給大家分享了python3實(shí)現(xiàn)域名查詢和whois查詢功能的詳細(xì)代碼,有需要的朋友參考學(xué)習(xí)下。2018-06-06
python腳本之一鍵移動(dòng)自定格式文件方法實(shí)例
這篇文章主要給大家介紹了關(guān)于python腳本之一鍵移動(dòng)自定格式文件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09

