游标对象 2019/1/24
就是对数据库进行具体的操作了,比如增、删、改、查等等一系列操作都可以完成
1.游标类型:
类型 | 描述 |
Cursor | 普通的游标对象,默认创建的游标对象 |
SSCursor | 不缓存游标,主要用于当操作需要返回大量数据的时候 |
DictCursor | 以字典的形式返回操作结果 |
SSDictCursor | 不缓存游标,将结果以字典的形式进行返回 |
class pymysql.cursors.Cursor(connection)#游标结果作为元祖的元祖返回
说明:
这是您用于与数据库交互的对象。
不要自己创建Cursor实例。调用connections.Connection.cursor()
class pymysql.cursors.SSCursor(connection)#无缓冲游标结果作为元祖的元祖返回,
用途:
用于返回大量数据查询,或慢速网络连接到远程服务器
不将每行数据复制到缓冲区,根据需要获取行。客户端内存使用少
在慢速网络上或结果集非常大时行返回速度快
限制:
MySQL协议不支持返回总行数,判断有多少行唯一方法是迭代返回的每一行。
目前无法向后滚动,因为只有当前行保存在内存中。
class pymysql.cursors.DictCursor(connection) #将结果作为字典返回游标
class pymysql.cursors.SSDictCursor(connection)#无缓冲游标结果作为字典返回
2.游标属性: 只读
# PEP 249 - Python数据库API规范v2.0
name #必需
type_code#必需
display_size
internal_size
precision
scale
null_ok
cursor.description#返回游标活动状态 #(('VERSION()', 253, None, 24, 24, 31, False),)
包含7个元素的元组:
(name, type_code, display_size, internal_size, precision, scale, null_ok)
游标属性:
cursor.max_stmt_length#1024000
cursor.rownumber#5 #当前结果集中游标所在行的索引(起始行号为 0)
cursor.arraysize#1 #此读/写属性指定用.fetchmany()一次获取的行数。
# 默认1表示一次获取一行;也可以用于执行.executemany()
cursor.lastrowid#None #只读属性提供上次修改行的rowid
# DB仅在执行单个INSERT 操作时返回rowid 。
# 如未设rowid或DB不支持rowid应将此属性设置为None
# 如最后执行语句修改了多行,例如用INSERT和.executemany()时lastrowid语义是未定义
cursor.rowcount #5 #最近一次 execute() 创建或影响的行数
# 如无cursor.execute()或接口无法确定最后一个操作的rowcount则该属性为-1
# 该行数属性可以在动态更新其值的方式来编码。
# 这对于仅在第一次调用.fetch()方法后返回可用rowcount值的 数据库非常有用。
3.游标方法:连接关闭
cursor.connection()#创建此游标对象的数据库连接
cursor.close() #关闭此游标对象
3.11方法:查询
cursor.excute(query,args = None)#执行数据库操作(查询或命令)
参数:
query:str 表示要执行的SQL语句
args:(元组,列表或字典) - 与查询一起使用的参数。用于给SQL传入参数,是可选的。
返回:
int受影响的行数
注意:
# 如args是列表或元组用%s作为SQL 语句中的占位符,args是dict用%(name)s作为占位符。
# 重复操作最好用.setinputsizes()提前指定参数类型和大小。参数与预定义信息不匹配是合法的;
# 参数也可为元组列表,如在单个操作中插入多行,不推荐:应用.executemany()
实例:#向Cu_table表中的id字段中插入数据
str_insert= "INSERT INTO Cu_table (id) VALUES (%s)"# 参数是元组时
cursor.execute(str_insert,('123'))
arg = {'id':'id'}# 参数是字典时
str_insert= "INSERT INTO Cu_table (id) VALUES (%(id)s)"
cursor.execute(str_insert,arg)
3.12方法:查询
cursor.excutemany(query, args)#执行多个数据库查询或命令
参数:
query - 要在服务器上执行的查询
args - 序列或映射的序列。它用作参数。
返回:
受影响的行数(如果有)
说明:
提高多行INSERT和REPLACE的性能。否则它等同于使用execute()循环遍历args
executemany()生成的最大语句大小为max_allowed_packet - packet_header_size
cursor.max_stmt_length #1024000
con.max_allowed_packet#16777216
实例:
str_insert = "INSERT INTO Cu_table (id) VALUES (%s)"
cursor.executemany(str_insert,['A','B','C','D']) #一次插入A B C D 四个值
3.21方法:获取结果
cursor.fetchone()#获取查询结果的下一行
返回:
单个序列元祖或None
实例:
str_insert = "SELECT * FROM Cu_table"
cursor.execute(str_insert)
result = cursor.fetchone()
print(result)
3.22方法:获取结果
cursor.fetchmany(size=None)#获取查询结果前size行,默认cursor.arraysize=1行
返回:
序列的序列(例如元组的元祖)
实例:
str_insert = "SELECT * FROM Cu_table"
cursor.execute(str_insert)
result = cursor.fetchmany(3) # 获取前三行
print(result)
3.23方法:获取结果
cursor.fetchall()#获取所有查询的结果行
返回:
序列的序列(例如元组的元祖)
说明:
对于大型查询来说,它是无用的,因为它是缓冲的
实例:
str_insert = "SELECT * FROM Cu_table"
cursor.execute(str_insert)
result = cursor.fetchall()
pd.DataFrame(list(result))
注意:如fetchall(),fetchmany(),fetchone()同时作用于同一个查询时,每个方法执行开头是上一个方法执行的结尾
也就是说,如果前面执行了fetchall()方法,后面执行的fetchmany()或fetchone()方法是获取不到结果。
比如:
str_insert = "SELECT * FROM Cu_table"
cursor.execute(str_insert )
result = cursor.fetchall()
print(result) # 这里会输出所有结果。。。
result = cursor.fetchone()
print(result) # None
result = cursor.fetchmany(3)
print(result) # ()
3.24方法:迭代获取结果
cursor .__iter__()#创建一个可迭代对象(可选)
实例:
cursor.execute("SELECT * FROM new_futures.m1809")
it=cursor.__iter__()
it.__next__()#获取结果集的下一行返回元祖
pd.DataFrame(list(it))
3.3方法:调用函数
cursor.callproc(procname, args=())#调用数据库中的存储过程
参数:
procname表示数据库中存储过程的名字,args表示为存储过程传入的参数。
返回:
返回原始args
调用的结果作为输入序列的修改副本返回。
该过程还可以提供结果集作为输出。然后必须通过标准.fetch *()方法使其可用
调用无参数存储过程:cursor.callproc('p2') #等价cursor.execute("call p2()")
调用有参数存储过程:cursor.callproc('p1', args=(1, 22, 3, 4))
3.4方法:nextset()
cursor.nextset()#移到下一个结果集(如果支持的话)当前集中丢弃任何剩余行
# 如没有更多集返回None。否则返回true,后续对.fetch () 方法的调用将返回下一个结果集中的行
3.5方法: scroll
cursor.scroll(value [,mode ='relative' ])#根据模式将结果集中的光标滚动到新位置
# 如果mode是relative(默认值),则将值作为结果集中当前位置的偏移量,
# 如果设置为absolute,则value表示绝对目标位置。
# cursor.scroll(1,mode='relative') # 相对当前位置移动
# cursor.scroll(2,mode='absolute') # 相对绝对位置移动
3.6方法:mogrify转换字符串
cursor.mogrify(query, args=None)#通过调用execute()方法返回发送到数据库的确切字符串
作用:
转换,把SQL语句和参数相结合,对其中特殊字符进行加\转义,
然后返回一个execute()方法发送到数据库确切执行的字符串,避免注入语句生成。
实例1:
str_query= "DELETE FROM Cu_table WHERE id=%s AND name=%s"
stri = cursor.mogrify(str_query,["u1' or '1'-- ","Tom"])
print(stri)
# DELETE FROM Cu_table WHERE id='u1\' or \'1\'-- ' AND name='Tom'
实例2:
# INSERT INTO m1809(No,open, close) VALUES (5,2881,2882), (6,2883,2884);数据库插入
args = [(5,2881,2882), (6,2883,2884)]
args_str = ','.join(cursor.mogrify("%s", (x, )) for x in args)#'(5,2881,2882),(6,2883,2884)'
cursor.execute("INSERT INTO m1809(No,open, close) VALUES "+args_str)
实例3:
实例3:pymysql库
args_str = cursor.mogrify("%s", 'datadir')
cursor.execute('show global variables like'+args_str)
cursor.fetchall()# [{'Variable_name': 'datadir', 'Value': 'D:\\Future_Data\\'}]会出现警告
用mysql.connector 创建一个连接再次运行ok
import mysql.connector as mysqlcon
db_name='new_futures'
con = mysqlcon.connect(host = "127.0.0.1",user = "root",password = "root",
database = db_name,charset = 'utf8mb4')
cursor = con.cursor()#获取游标
cursor.execute('show global variables like "%datadir%"')
cursor.fetchall()#[('datadir', 'D:\\Future_Data\\')]
3.7方法:设置
cursor .setinputsizes(sizes)#预定义操作参数的内存区域;调用.execute ()之前使用
# sizes被指定为一个序列 - 每个输入参数一个项目。该项应该是与将要使用的输入对应的Type对象,
# 或者应该是指定字符串参数的最大长度的整数。如果该项为 None,则不会为该列保留预定义的内存区域
# (这对于避免大输入的预定义区域很有用)。实现可以自由地使用此方法,用户可以不使用它
cursor .setoutputsizes(sizes[,col])#为大列的提取设置列缓冲区大小(如LONG,BLOB等)。
# 该列被指定为结果序列的索引。不指定列将为游标中的所有大列设置默认大小。
# 调用.execute ()之前使用;实现可以自由地使用此方法,用户可以不使用它
4设置数据返回的类型:
默认获取的数据是元祖的元祖类型,更改为字典类型
#方式1:pymysql.connection()中指定参数
conn = pymysql.connect(host = "127.0.0.1",user = "root",password = "root",database = "new_futures",
charset = 'utf8',cursorclass = pymysql.cursors.DictCursor)
#方式2:conn.cursor()中指定参数
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
pd.DataFrame(list(rs))#rs为元祖:((1, '豆粕1','m1809',),(2,'豆粕2','m1809',),...,(...))
pd.DataFrame(rs1) #rs1为字典:[{'No': 1,'name': '豆粕1','code': 'm1809'},{...}]
5.传入变量参数的方法:
import pymysql
con=pymysql.connect( host='localhost',user='root',password='root',database='new_futures')
cursor=con.cursor()
5.1格式1:仅仅传入数值
5.1.1参数是元组
#必须加括号,只能是(%s)格式; 参数必须是(str,)
# 实例1.1.1:一个参数
str_insert= "INSERT INTO m1805 (id) VALUES (%s)"# 只能是(%s)格式
cursor.execute(str_insert,('7')) #必须加括号必须是字符串
con.commit()
# 实例1.1.2:多个参数
str_insert= "INSERT INTO m1805 (id,name) VALUES (%s,%s)"# 只能是(%s)格式
cursor=con.cursor()
cursor.execute(str_insert,('123','Jim'))#必须加括号必须是字符串
con.commit()
5.1.2参数是字典
#必须加括号包括,只能是%(字典键名)s格式; 参数必须是字典
#实例1.2.1:
arg = {'x':'33'}
str_insert= "INSERT INTO m1805 (id) VALUES (%(x)s)"
cursor.execute(str_insert,arg)
con.commit()
#实例1.2.2:
arg = {'x':'44','y':'Bob'}
str_insert= "INSERT INTO m1805 (id,name) VALUES (%(x)s,%(y)s)"
cursor.execute(str_insert,arg)
con.commit()
5.2格式2:传入变量
# 实例2.1:传入变量到语句%s+传入数值到(%s) cursor.execute(后面必须加括号)
table_name='m1805';id1='id';name='name';id_v='55';name_v='Smith'
str_insert= "INSERT INTO %s (%s,%s) "%(table_name,id1,name)#传入变量
str_insert=str_insert+"VALUES (%s,%s)"# 传入变量的数值;必须分开写,佛则会把变量值当成列或表名寻找,最后报错
cursor.execute(str_insert,(id_v,name_v))#必须加括号必须是字符串
con.commit()
# 实例2.2:传入变量到语句%s+传入数值到语句'%d','%s'分开书写
table_name='m1805';id1='id';name='name';id_v=66;name_v='Smith'
str_insert= "INSERT INTO %s (%s,%s) "%(table_name,id1,name)
str_insert=str_insert+"VALUES ('%d','%s')"%(id_v,name_v)#注意 ('%d','%s')不同于上面,这样书写会将变量解析为指定的类型
cursor.execute(str_insert)
con.commit()
# 实例2.3.1:传入变量到语句%s +传入数值到语句'%d','%s'合并书写
table_name='m1805';id1='id';name='name';id_v=77;name_v='Smith'
str_insert= "INSERT INTO %s (%s,%s) VALUES ('%d','%s')"%(table_name,id1,name,id_v,name_v)
cursor.execute(str_insert)
con.commit()
# 实例2.3.2:综合运用
#日期以字符串形式传入
table_name='m1805';id1='id';name='name';id_v=88;name_v='Smith';
date='2019-1-27';time='12:05:05'
str_insert= "INSERT INTO %s (%s,%s,%s,%s) VALUES ('%d','%s','%s','%s')"%(
table_name,id1,name,'date','time',id_v,name_v,date,time)
cursor.execute(str_insert)
con.commit()
# 实例2.4:错误的用法
table_name='m1805';id1='id';name='name';id_v=88;name_v='Smith';date='2019-1-27';time='12:05:05'
str_insert= "INSERT INTO '%s' ('%s','%s') VALUES ('%d','%s')"%(table_name,id1,name,id_v,name_v)
str_insert=cursor.mogrify(str_insert)
print(str_insert)
#cursor.execute(str_insert)#
#con.commit()
'''''''''
INSERT INTO 'm1805' ('id','name') VALUES ('88','Smith')
'''