python操作MySQL、pymysql模块、SQL注入攻击

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • python操作MySQL
    • 用python连接mysql的基本语法
    • 用python 创建&删除表
    • 用python操作事务处
  • pymysql模块(增删改查)
    • 创建游标时,可以指定返回值类型为其他(默认是元组)
    • pymysql 增
    • pymysql 删
    • pymysql 改
    • pymysql 查
      • fetchone 获取一条
      • fetchmany 获取多条
      • fetchall 获取所有
      • 自定义搜索查询的位置
        • 相对滚动 relative
        • 绝对滚动 absolute
  • SQL注入攻击
    • sql注入的现象
    • 预处理机制:防止sql注入现象


python操作MySQL

用python连接mysql的基本语法

创建连接conn→创建游标对象cursor→执行sql语句execute→获取数据fetchone→释放游标对象cursor→关闭连接conn

# (1) 创建连接  host  user  password  database 这四个参数必须写
conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db0826",charset="utf8",port=3306)

# (2) 创建游标对象(该对象可以操作数据库增删改查)
cursor = conn.cursor()

# (3) 执行sql语句
sql = "select * from employee"
# 返回的是数据的总条数
res = cursor.execute(sql)
print(res)

# (4)获取数据 fetchone 获取一条
res = cursor.fetchone()
res = cursor.fetchone()
print(res)

# (5) 释放游标对象
cursor.close()

# (6) 关闭连接
conn.close()

用python 创建&删除表

conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db0826")
cursor = conn.cursor()

# 1.创建一张表
sql = """
create table t1(
id int unsigned primary key auto_increment,
first_name char(10) not null,
last_name char(10) not null,
age int unsigned,
sex tinyint,
money float
)
"""

# res = cursor.execute(sql)
# print(res)

# 2.查看表结构
sql = "desc t1"
res = cursor.execute(sql)
print(res) # 返回的是字段的个数
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) # 无意义返回值
except:
	pass
	
cursor.close()
conn.close()

用python操作事务处

pymysql 操作事务处理时,需要commit提交数据,才会变化,否则rollback回滚.恢复到最初状态

请注意:你sql语句里写的是增删改,你得到的execute的返回值没有任何意义,
所以你fetchone是无效的,只有你sql语句写的是查询的操作,fetchone才能获取到数据     
"""pymysql 默认开启事务的,所有增删改的数据必须提交,否则默认回滚;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)
# 一般在查询的时候,通过fetchone来获取结果
res1 = cursor.fetchone()
print(res1)

cursor.close()
conn.close()

pymysql模块(增删改查)

"""
	python 操作mysql增删改时,默认是开启事务的,
	必须最后commit提交数据,才能产生变化
	
	提交数据: commit 
	默认回滚: rollback
	
"""

创建游标时,可以指定返回值类型为其他(默认是元组)

import pymysql

conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db005")
# 默认获取查询结果时是元组,可以设置返回字典;  cursor=pymysql.cursors.DictCursor
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

pymysql 增

cursor.executemany:可以一次插入多条数据

cursor.lastrowid:获取最后插入这条数据的id(仅针对单条数据插入)
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
# 获取最后插入这条数据的id号
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) # 返回插入的条数
# 插入5条数据中的第一条数据的id
print(cursor.lastrowid)
# 获取最后一个数据的id
sql = "select id from t1 order by id desc limit 1"
res = cursor.execute(sql)
print(res)
# 获取结果,返回元组
res = cursor.fetchone()
print(res["id"])
'''
# 默认元组 : (57, '高', '大奥', 1, 20, 80000.0)
# 返回字典 : {'id': 51, 'first_name': '高', 'last_name': '大奥', 'sex': 1, 'age': 20, 'money': 80000.0}
'''

pymysql 删

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("删除失败")

pymysql 改

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("修改失败")

pymysql 查

要注意:fetchone fetchmany fetchall 都是基于上一条数据往下查询

fetchone  获取一条

fetchmany 获取多条

fetchall  获取所有
sql = "select * from t1"
res = cursor.execute(sql)
print(res) # 针对于查询语句来说,返回的res是总条数;

fetchone 获取一条

res = cursor.fetchone()
print(res)
res = cursor.fetchone()
print(res)

fetchmany 获取多条

res = cursor.fetchmany() # 默认获取的是一条数据,返回列表,里面里面是一组一组的字典;
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}
]
"""

data一共是三条数据,我们可以通过for循环取出每一条数据,并且按照自己的格式进行拼接

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)

fetchall 获取所有

sql = "select * from t1"
res = cursor.execute(sql)
print(res) # 总条数

data = cursor.fetchall()
print(data)

自定义搜索查询的位置

相对滚动 relative

相对滚动 (正数相对于当前位置往后滚,负数相对于当前位置往后滚.)

# 向前滚3个
cursor.scroll(3,mode="relative")
res = cursor.fetchone()
print(res)

# 往后滚2个
cursor.scroll(-2,mode="relative")
res = cursor.fetchone()
print(res)

绝对滚动 absolute

绝对滚动 , 永远基于第一条数据的位置进行移动

cursor.scroll(0,mode="absolute")
print(cursor.fetchone())

cursor.scroll(1,mode="absolute")
print(cursor.fetchone())

cursor.scroll(3,mode="absolute")
print(cursor.fetchone())

# 往前滚没有数据,超出范围 error报错
cursor.scroll(-1,mode="absolute")
print(cursor.fetchone())

# 在进行增删改查时,必须提交数据,才会产生影响.
conn.commit()
cursor.close()
conn.close()

SQL注入攻击

先创建一张用户名-密码表

sql='''
create table usr_pwd(
id int unsigned primary key auto_increment,
username varchar(255) not null,
password varchar(255) not null
'''
)

sql注入的现象

现象:绕开账号密码登录成功

import pymysql

user = input("请输入您的用户名>>>")
pwd  = input("请输入您的密码>>>")

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没查到失败
# res=cursor.fetchone()
"""
select * from usr_pwd where username='2222' or 4=4 -- aaa' and password='' 
相当于 : select * from usr_pwd where 4=4; 绕开了账户和密码的判断 -- 代表的是注释;
后面的字符串都会被注释掉, 前面账号虽然是错的 但是 4=4是真的 绕开了账号和密码的判断;
"""
if res:
	print("登录成功")
else:
	print("登录失败")

cursor.close()
conn.close()

预处理机制:防止sql注入现象

在执行sql语句之前,提前对sql语句中出现的字符进行过滤优化,避免sql注入攻击
execute( sql , (参数1,参数2,参数3 … ) ) execute2个参数默认开启预处理机制

攻击手段 = 填写 234234’ or 100=100 – sdfsdfsdfsdf 尝试攻击

import pymysql
user = input("请输入用户名: >>> ").strip()
pwd = input("请输入密码: >>> ").strip()

conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db0826")
cursor = conn.cursor()
sql = "select * from usr_pwd where username=%s and password=%s"
res = cursor.execute(sql, (user,pwd) )

print("登陆成功" if res  else "登录失败")

cursor.close()
conn.close()

你可能感兴趣的:(python笔记,mysql,python,数据库)