Python:mysql.connector中获取数据库值的一些问题
在MySQL官网有关于Python版的MySQL Connector的使用介绍:MySQL Connector/Python Developer Guide
但似乎这个介绍中的例子都过于浅显,尤其是对于执行MySQL命令后获取值的部分;这两天看了看源码发现还有好多新东西。
来自官网的介绍似乎是要这样使用:
import mysql.connector
db = {
'user': 'root',
'password': '123456',
'database': '123061'
}
cnx = mysql.connector.connect(
user=db['user'], password=db['password'], database=db['database'])
cursor = cnx.cursor()
query = "SELECT name FROM station"
cursor.execute(query)
for (name,) in cursor:
print(name)
cursor.close()
cnx.close()
简单而言,
cursor = cnx.cursor()
实际上是创建了类MySQLCursor
的一个实例,当
cursor.execute(query)
后,数据库操作得到的每一条结果都作为一个元组(tuple
),cursor
实际上就是作为一个迭代器(iterator
),每次使用方法__next__()
即返回一条结果。
当迭代器中无值,即每条结果都返回后,如果继续执行__next__()
,则会产生StopIteration
错误。
所以如果不希望使用for...in...
的话,可以使用:
try:
cursor.__next__()
except StopIteration:
print('no more result')
另外还需要注意的是,如果迭代器中的结果没有全部取出,是不能再次执行cursor.execute()
的,也就是说不能在for...in...
循环内再次操作数据库,而是需要首先将值全部取出。
实际上,数据库操作返回的结果也并不一定要是tuple,还可以是dictionary,只需要在创建cursor时声明:
cursor = cnx.cursor(dictionary = True)
返回的dictionary中key都是数据库table中的字段名,而如果希望key不是字段名,可以在MySQL语句中声明,如:
query = "SELECT name AS 名字 FROM station"
这样返回的dictionary中key即“名字”
__next__()
方法的源码:
def __next__(self):
"""
Used for iterating over the result set. Calles self.fetchone()
to get the next row.
"""
try:
row = self.fetchone()
except errors.InterfaceError:
raise StopIteration
if not row:
raise StopIteration
return row
可以看到每次执行__next__()
实际上都是在执行fetchone()
而fetchone()
的源码:
def fetchone(self):
"""Returns next row of a query result set
Returns a tuple or None.
"""
row = self._fetch_row()
if row:
return self._connection.converter.row_to_python(
row, self.description)
return None
这里不深究fetchone()
了,实际上这里还有fetchmany()
和fetchall()
:
def fetchmany(self, size=None):
res = []
cnt = (size or self.arraysize)
while cnt > 0 and self._have_unread_result():
cnt -= 1
row = self.fetchone()
if row:
res.append(row)
return res
def fetchall(self):
if not self._have_unread_result():
raise errors.InterfaceError("No result set to fetch from.")
(rows, eof) = self._connection.get_rows()
if self._nextrow[0]:
rows.insert(0, self._nextrow[0])
res = [self._connection.converter.row_to_python(row, self.description)
for row in rows]
self._handle_eof(eof)
rowcount = len(rows)
if rowcount >= 0 and self._rowcount == -1:
self._rowcount = 0
self._rowcount += rowcount
return res
我觉得fetchall()
才是被忽略的好东西,fetchall()
返回的是由tuple
组成的list
,这样避免了for...in...
这种讨厌的东西,比如:
cursor.execute(query)
res=cursor.fetchall()