安装
pip3 install pymysql
连接、执行sql、关闭(游标)
import pymysql mysql_connect_dict={ 'host':'127.0.0.1', 'port':3306, 'user':'yycenter', 'password':'qwe123', 'db':'testmysql', 'charset':'utf8' } # 连接数据库 # conn = pymysql.connect(**mysql_connect_dict) # 指定以dict形式返回,默认以元祖形式 conn = pymysql.connect(**mysql_connect_dict,cursorclass=pymysql.cursors.DictCursor) print(conn) # 创建游标 cursor = conn.cursor() # 执行SQL,并返回收影响行数 effect_row = cursor.execute("select * from test1") print(effect_row) # 6条记录 # 关闭游标 cursor.close() # 关闭连接 conn.close()
execute之sql注入
注意:符号--会注释掉它之后的sql,正确的语法:--后至少有一个任意字符
根本原理:就根据程序的字符串拼接name='%s',我们输入一个xxx' -- haha,用我们输入的xxx加'在程序中拼接成一个判断条件name='xxx' -- haha'
sql='select * from userinfo where name="%s" and password="%s"' %(user,pwd) #注意%s需要加引号 #1、sql注入之:用户存在,绕过密码 egon' -- 任意字符 #2、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 = pymysql.connect(**mysql_connect_dict,cursorclass=pymysql.cursors.DictCursor) print(conn) # 创建游标 cursor = conn.cursor() # 执行SQL,并返回收影响行数 effect_row = cursor.execute("select * from test1") print(effect_row) # 6条记录 # #执行sql语句 # #part1 sql="insert into test1(name,grade) values('egon',99)" res=cursor.execute(sql) # 执行sql语句,返回sql影响成功的行数 print(res) # 1 # # #part2 sql='insert into test1(name,grade) values(%s,%s);' res=cursor.execute(sql, ("alex",100)) # 执行sql语句,返回sql影响成功的行数 print(res)# 1 # # # part3 sql = 'insert into test1(name,grade) values(%s,%s);' res = cursor.executemany(sql,[('egon1',99),('egon2',88),('egon3',77)]) # 执行sql语句,返回sql影响成功的行数 print(res) # 3 执行sql语句,返回sql影响成功的行数 # conn.commit() # 提交后才发现表中插入记录成功 # part4 sql = 'update test1 set grade = %s where name= %s;' res = cursor.execute(sql,(66,'egon')) # 执行sql语句,返回sql影响成功的行数 print(res) # 1 执行sql语句,返回sql影响成功的行数 conn.commit() # 提交后才发现表中插入记录成功 # part5 sql = 'delete from test1 where name= %s;' res = cursor.execute(sql,('egon2')) # 执行sql语句,返回sql影响成功的行数 print(res) # 1 执行sql语句,返回sql影响成功的行数 conn.commit() # 提交后才发现表中插入记录成功 # 关闭游标 cursor.close() # 关闭连接 conn.close()
查询
# 指定以dict形式返回,默认以元祖形式 conn = pymysql.connect(**mysql_connect_dict,cursorclass=pymysql.cursors.DictCursor) print(conn) # 创建游标 cursor = conn.cursor() # 执行SQL,并返回收影响行数 effect_row = cursor.execute("select * from test1") print(effect_row) # res1=cursor.fetchone() # 获取剩余结果的第一行数据 res2=cursor.fetchmany(2) # 获取剩余结果前n行数据 res3=cursor.fetchall() # 获取剩余结果所有数据 print(res1) #{'id': 1, 'name': 'aa', 'grade': 99} print(res2) #[{'id': 2, 'name': 'bb', 'grade': 55}, {'id': 3, 'name': 'cc', 'grade': 88}] print(res3) # [{'id': 9, 'name': 'y', 'grade': 44}, {'id': 10, 'name': 'y', 'grade': 99}, {'id': 11, 'name': 'y', 'grade': 55}] res4=cursor.fetchall() # 获取剩余结果所有数据 print(res4) # 空,数据已经取完 # 在fetch数据时按照顺序进行,可以使用cursor.scroll(num,mode)来移动游标位置 cursor.scroll(0, mode='absolute') # 相对绝对位置移动 res5=cursor.fetchmany(2) # 获取剩余结果前2行数据 print(res5) # [{'id': 1, 'name': 'aa', 'grade': 99}, {'id': 2, 'name': 'bb', 'grade': 55}] cursor.scroll(2, mode='relative') # 相对当前位置移动2条记录,总记录数还剩下2条 res6=cursor.fetchall() # 获取剩余结果所有数据 print(res6) # [{'id': 10, 'name': 'y', 'grade': 99}, {'id': 11, 'name': 'y', 'grade': 55}] # 关闭游标 cursor.close() # 关闭连接 conn.close()
获取新创建数据自增ID
可以获取到最新自增的ID,也就是最后插入的一条数据ID
# conn = pymysql.connect(**mysql_connect_dict) # 指定以dict形式返回,默认以元祖形式 conn = pymysql.connect(**mysql_connect_dict,cursorclass=pymysql.cursors.DictCursor) print(conn) # 创建游标 cursor = conn.cursor() # 执行SQL,并返回收影响行数 effect_row = cursor.execute("select * from test1") sql = 'insert into test1(name,grade) values(%s,%s);' res = cursor.executemany(sql,[('egon1',99),('egon2',88),('egon3',77)]) # 执行sql语句,返回sql影响成功的行数 print(res) # 3 执行sql语句,返回sql影响成功的行数 conn.commit() #获取自增id new_id = cursor.lastrowid print(new_id) #31 # 关闭游标 cursor.close() # 关闭连接 conn.close()
调用存储过程
调用无参存储过程
# 指定以dict形式返回,默认以元祖形式 conn = pymysql.connect(**mysql_connect_dict,cursorclass=pymysql.cursors.DictCursor) print(conn) # 创建游标 cursor = conn.cursor() # 执行SQL,并返回收影响行数 effect_row = cursor.execute("select * from test1") # 无参数存储过程 cursor.callproc('p1') # 等价于cursor.execute("call p1()") # create procedure p1() # BEGIN # INSERT into test1(name,grade) values('egon4',100); # commit; # END row_1 = cursor.fetchone() print(row_1) conn.commit() # 关闭游标 cursor.close() # 关闭连接 conn.close()
b、调用有参存储过程
# 指定以dict形式返回,默认以元祖形式 conn = pymysql.connect(**mysql_connect_dict,cursorclass=pymysql.cursors.DictCursor) print(conn) # 创建游标 cursor = conn.cursor() # 执行SQL,并返回收影响行数 effect_row = cursor.execute("select * from test1") # 有参数存储过程 cursor.callproc('p2',args=('egon6',99)) # 等价于cursor.execute("call p1()") # delimiter // # CREATE PROCEDURE p2(IN p_in1 VARCHAR(20),IN p_in2 int) # BEGIN # INSERT into test1(name,grade) values(p_in1,p_in2); # commit; # END // # delimiter ; # 获取执行完存储的参数,参数@开头 cursor.execute("select @_p2_0,@_p2_1;") #@p2_0代表第一个参数,@p2_1代表第二个参数,即返回值 row_1 = cursor.fetchone() print(row_1) # '@_p2_0': 'egon6', '@_p2_1': 99} conn.commit() # 关闭游标 cursor.close() # 关闭连接 conn.close()
使用with简化连接过程
每次都连接关闭很麻烦,使用上下文管理,简化连接过程
import pymysql import contextlib # 定义上下文管理器,连接后自动关闭连接 @contextlib.contextmanager def mysql(): mysql_connect_dict={ 'host':'127.0.0.1', 'port':3306, 'user':'yycenter', 'password':'qwe123', 'db':'testmysql', 'charset':'utf8' } # 连接数据库 # conn = pymysql.connect(**mysql_connect_dict) # 指定以dict形式返回,默认以元祖形式 conn = pymysql.connect(**mysql_connect_dict,cursorclass=pymysql.cursors.DictCursor) print(conn) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) try: yield cursor finally: conn.commit() cursor.close() conn.close() # 执行sql with mysql() as cursor: print(cursor) row_count = cursor.execute("select * from test1") row_1 = cursor.fetchone() print (row_count, row_1) # 8 {'id': 1, 'name': 'aa', 'grade': 99}