python操作mysql
一、基本操作
- 导入pymysql模块
- 建立数据库连接对象conn
- 通过conn创建操作sql的游标对象
- 编写sql交给cursor执行
- 如果是查询,通过cursor对象,获取结果
- 操作完毕,端口操作与连接
1)#导入pymysql模块
import pymysql
2)#建立数据库连接对象conn
conn = pymysql.connect(user = 'root',password = '12345678',database = 'yjy') #此处还可以写autocommit=True,待会可以自动提交事务
3)#通过conn创建操作sql的游标对象
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 注:游标不设置参数,查询的结果就是数据元组,数据没有标识性
# 设置pymysql.cursors.DictCursor,查询的结果是字典,key是表的字段
4)#编写sql交给cursor执行
# #先创建一个表
sql1 = 'create table tt(id int primary key auto_increment ,x int ,y int);'
cursor.execute(sql1)
mysql> desc tt;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| x | int(11) | YES | | NULL | |
| y | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+----------------+
#插入数据
# sql2 = 'insert into tt values(%s, %s, %s)'
sql2 = 'insert into tt(x,y) values(%s, %s)'
cursor.execute(sql2,(1,10))
cursor.execute(sql2,(2,20))
cursor.execute(sql2,(3,30))
conn.commit() #在建立对象conn时不设置autocommit=True时,必须要提交事务,不然的话写不到数据库
mysql> select * from tt;
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | 1 | 10 |
| 2 | 2 | 20 |
| 3 | 3 | 30 |
+----+------+------+
'''还可以插入多条数据'''
cursor.executemany(sql2,[(4,40),(5,50),(6,60)]) #这里是executemany,而且一定要记住中括号
conn.commit()
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | 1 | 10 |
| 2 | 2 | 20 |
| 3 | 3 | 30 |
| 4 | 4 | 40 |
| 5 | 5 | 50 |
| 6 | 6 | 60 |
+----+------+------+
'''删'''
sql3= 'delete from tt where id = %s'
cursor.executemany(sql3,(2,3,4,5))
conn.commit()
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | 1 | 10 |
| 6 | 6 | 60 |
+----+------+------+
'''改'''
sql4 = 'update tt set y=888 where id = 6'
cursor.execute(sql4)
conn.commit()
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | 1 | 10 |
| 6 | 6 | 888 |
+----+------+------+
'''查'''
sql5 = 'select * from tt'
res = cursor.execute(sql5)
print(res) #8
5)#如果是查询,通过cursor对象,获取结果
r1 = cursor.fetchone() #偏移一条数据取出
print(r1) #{'id': 1, 'x': 1, 'y': 10}
r2 = cursor.fetchmany(3) #偏移3条数据取出
print(r2)
#[{'id': 2, 'x': 2, 'y': 20}, {'id': 3, 'x': 3, 'y': 30}, {'id': 4, 'x': 4, 'y': 40}]
r3 = cursor.fetchall() #把偏移后剩余的全部取出来
print(r3)
#[{'id': 5, 'x': 5, 'y': 50}, {'id': 6, 'x': 6, 'y': 60}, {'id': 7, 'x': 7, 'y': 70}, {'id': 8, 'x': 8, 'y': 80}]
6)#操作完毕,端口操作与连接
cursor.close() #关闭游标对象
conn.close() #关闭数据库连接对象
二、事务
import pymysql
conn = pymysql.connect(user = 'root',password = '12345678',database = 'yjy')
cursor = conn.cursor(pymysql.cursors.DictCursor)
#对表的重复创建做一个异常处理,防止报错
try:
sql1 = 'create table ts(id int primary key auto_increment ,name char(8),money int)'
cursor.execute(sql1)
except Exception:
print('表已经创建')
pass
#在空表中插入数据
row = cursor.execute('select * from ts') #检查一下表里面是否有数据
if not row: #如果没有数据,插入数据
sql = 'insert into ts(name,money) values(%s,%s)'
res = cursor.executemany(sql, [('yjy', 10), ('wwb', 30)])
conn.commit()
#在事务中出现的失败,处理一下异常
try:
sql1 = 'update ts set money=money-1 where name="yjy"'
r1 = cursor.execute(sql1)
sql2 = 'update ts set money=money+1 where name="wwb"' # 转入的人不存在
r2 = cursor.execute(sql2)
except:
print('转账执行异常')
conn.rollback() #回滚
else:
print('转账没有异常')
if r1 == 1 and r2 == 1:
print('转账成功')
conn.commit() #提交事务
else:
conn.rollback() #回滚
mysql> select * from ts;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | yjy | 10 |
| 2 | wwb | 30 |
+----+------+-------+
2 rows in set (0.00 sec)
mysql> select * from ts;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | yjy | 9 |
| 2 | wwb | 31 |
+----+------+-------+
2 rows in set (0.00 sec)
三、sql注入
import pymysql
from pymysql.cursors import DictCursor
conn = pymysql.connect(user='root', passwd='12345678', db='yjy')
cursor = conn.cursor(DictCursor)
try:
sql = 'create table user(id int primary key auto_increment, name char(4), password char(6))'
row = cursor.execute(sql)
print(row)
except:
print('表已创建')
pass
# 空表才插入
row = cursor.execute('select * from user')
if not row:
sql = 'insert into user(name,password) values(%s,%s)'
row = cursor.executemany(sql, [('yjy', '123'), ( 'wwb', 'abc')])
conn.commit()
# 用户登录
usr = input('usr: ')
pwd = input('pwd: ')
#数据库验证
sql = 'select * from user where name=%s and password=%s'
row = cursor.execute(sql, (usr, pwd))
if row:
print('登录成功')
else:
print('登录失败')
# 自己拼接参数一定有sql注入,将数据的占位填充交给pymysql,下面这个方式是不正确的,对数据库中的数据不安全,用户随便用符号就可以登陆进去,所以,我们在上面的数据库验证得时候改了格式
"""
sql = 'select * from user where name="%s" and password="%s"' % (usr, pwd)
row = cursor.execute(sql)
if row:
print('登录成功')
else:
print('登录失败')
"""
# 知道用户名时
# 输入用户时:
# yjy" # => select * from user where name="yjy" #" and password="%s"
# 不自定义用户名时
# " or 1=1 # => select * from user where name=" " or 1=1 #" and password="%s"(就不需要输入密码了)
———————————————————————————————————————————————————————————————————————————————————
usr: yjy
pwd: 123
登录成功
四、索引
- 是添加给数据库表的字 的
- 给表创建键后该表不仅会形成表结构、表数据,还有键的B+结构图(加速查找的一个图)
- 键的结构图是需要维护的,在数据完成增、删、改操作时,只要影响到有键的字段,结构图都要维护一次
- 创建键后一定会降低 增、删、改 的效
- 键可以极大的加快查询速度(开发需求中,几乎业务都和查有关系)
- 建立键的方式:主键、外键、唯一键、index
#上面这个没有什么好说的,意思就是,当我们数据达到几十万条,几千万条,用索引查找时间会更快,这就是给表创建键的好处。