跟老齐学Python之使用Python查询更新数据库
回顾一下已有的战果:(1)连接数据库;(2)建立指针;(3)通过指针插入记录;(4)提交将插入结果保存到数据库。在交互模式中,先温故,再知新。
>>> #导入模块
>>> import mysqldb
>>> #连接数据库
>>> conn = mysqldb.connect(host="localhost",user="root",passwd="123123",db="qiwsirtest",port=3036,charset="utf8")
>>> #建立指针
>>> cur = conn.cursor()
>>> #插入记录
>>> cur.execute("insert into users (username,password,email) values (%s,%s,%s)",("老齐","9988",""))
1l
>>> #提交保存
>>> conn.commit()
如果看官跟我似的,有点强迫症,总是想我得看到数据中有了,才放芳心呀。那就在进入到数据库,看看。
mysql> select * from users;
+----+----------+----------+------------------+
| id | username | password | email |
+----+----------+----------+------------------+
| 1 | qiwsir | 123123 | |
| 2 | python | 123456 | |
| 3 | google | 111222 | |
| 4 | facebook | 222333 | |
| 5 | github | 333444 | |
| 6 | docker | 444555 | |
| 7 | 老齐 | 9988 | |
+----+----------+----------+------------------+
7 rows in set (0.00 sec)
刚才温故的时候,插入的那条记录也赫然在目。不过这里特别提醒看官,我在前面建立这个数据库和数据表的时候,就已经设定好了字符编码为utf8,所以,在现在看到的查询结果中,可以显示汉字。否则,就看到的是一堆你不懂的码子了。如果看官遇到,请不要慌张,只需要修改字符编码即可。怎么改?请google。网上很多。
温故结束,开始知新。
查询数据
在前面操作的基础上,如果要从数据库中查询数据,当然也可以用指针来操作了。
>>> cur.execute("select * from users")
7l
这说明从users表汇总查询出来了7条记录。但是,这似乎有点不友好,告诉我7条记录查出来了,但是在哪里呢,看前面在'mysql>'下操作查询命令的时候,一下就把7条记录列出来了。怎么显示python在这里的查询结果呢?
原来,在指针实例中,还要用这样的方法,才能实现上述想法:
fetchall(self):接收全部的返回结果行.
fetchmany(size=none):接收size条返回结果行.如果size的值大于返回的结果行的数量,则会返回cursor.arraysize条数据.
fetchone():返回一条结果行.
scroll(value, mode='relative'):移动指针到某一行.如果mode='relative',则表示从当前所在行移动value条,如果mode='absolute',则表示从结果集的第一行移动value条.
按照这些规则,尝试:
>>> cur.execute("select * from users")
7l
>>> lines = cur.fetchall()
到这里,还没有看到什么,其实已经将查询到的记录(把他们看做对象)赋值给变量lines了。如果要把它们显示出来,就要用到曾经学习过的循环语句了。
>>> for line in lines:
... print line
...
(1l, u'qiwsir', u'123123', )
(2l, u'python', u'123456', )
(3l, u'google', u'111222', )
(4l, u'facebook', u'222333', )
(5l, u'github', u'333444', )
(6l, u'docker', u'444555', )
(7l, u'\u8001\u9f50', u'9988', )
很好。果然是逐条显示出来了。列位注意,第七条中的u'\u8001\u95f5',这里是汉字,只不过由于我的shell不能显示罢了,不必惊慌,不必搭理它。
只想查出第一条,可以吗?当然可以!看下面的:
>>> cur.execute("select * from users where id=1")
1l
>>> line_first = cur.fetchone() #只返回一条
>>> print line_first
(1l, u'qiwsir', u'123123', )
为了对上述过程了解深入,做下面实验:
>>> cur.execute("select * from users")
7l
>>> print cur.fetchall()
((1l, u'qiwsir', u'123123', ), (2l, u'python', u'123456', ), (3l, u'google', u'111222', ), (4l, u'facebook', u'222333', ), (5l, u'github', u'333444', ), (6l, u'docker', u'444555', ), (7l, u'\u8001\u9f50', u'9988', ))
原来,用cur.execute()从数据库查询出来的东西,被“保存在了cur所能找到的某个地方”,要找出这些被保存的东西,需要用cur.fetchall()(或者fechone等),并且找出来之后,做为对象存在。从上面的实验探讨发现,被保存的对象是一个tuple中,里面的每个元素,都是一个一个的tuple。因此,用for循环就可以一个一个拿出来了。
看官是否理解其内涵了?
接着看,还有神奇的呢。
接着上面的操作,再打印一遍
>>> print cur.fetchall()
()
晕了!怎么什么是空?不是说做为对象已经存在了内存中了吗?难道这个内存中的对象是一次有效吗?
不要着急。
通过指针找出来的对象,在读取的时候有一个特点,就是那个指针会移动。在第一次操作了print cur.fetchall()后,因为是将所有的都打印出来,指针就要从第一条移动到最后一条。当print结束之后,指针已经在最后一条的后面了。接下来如果再次打印,就空了,最后一条后面没有东西了。
下面还要实验,检验上面所说:
>>> cur.execute('select * from users')
7l
>>> print cur.fetchone()
(1l, u'qiwsir', u'123123', )
>>> print cur.fetchone()
(2l, u'python', u'123456', )
>>> print cur.fetchone()
(3l, u'google', u'111222', )
这次我不一次全部打印出来了,而是一次打印一条,看官可以从结果中看出来,果然那个指针在一条一条向下移动呢。注意,我在这次实验中,是重新运行了查询语句。
那么,既然在操作存储在内存中的对象时候,指针会移动,能不能让指针向上移动,或者移动到指定位置呢?这就是那个scroll()
>>> cur.scroll(1)
>>> print cur.fetchone()
(5l, u'github', u'333444', )
>>> cur.scroll(-2)
>>> print cur.fetchone()
(4l, u'facebook', u'222333', )
果然,这个函数能够移动指针,不过请仔细观察,上面的方式是让指针相对与当前位置向上或者向下移动。即:
cur.scroll(n),或者,cur.scroll(n,"relative"):意思是相对当前位置向上或者向下移动,n为正数,表示向下(向前),n为负数,表示向上(向后)
还有一种方式,可以实现“绝对”移动,不是“相对”移动:增加一个参数"absolute"
特别提醒看官注意的是,在python中,序列对象是的顺序是从0开始的。
>>> cur.scroll(2,"absolute") #回到序号是2,但指向第三条
>>> print cur.fetchone() #打印,果然是
(3l, u'google', u'111222', )
>>> cur.scroll(1,"absolute")
>>> print cur.fetchone()
(2l, u'python', u'123456', )
>>> cur.scroll(0,"absolute") #回到序号是0,即指向tuple的第一条
>>> print cur.fetchone()
(1l, u'qiwsir', u'123123', )
至此,已经熟悉了cur.fetchall()和cur.fetchone()以及cur.scroll()几个方法,还有另外一个,接这上边的操作,也就是指针在序号是1的位置,指向了tuple的第二条
>>> cur.fetchmany(3)
((2l, u'python', u'123456', ), (3l, u'google', u'111222', ), (4l, u'facebook', u'222333', ))
上面这个操作,就是实现了从当前位置(指针指向tuple的序号为1的位置,即第二条记录)开始,含当前位置,向下列出3条记录。
读取数据,好像有点啰嗦呀。细细琢磨,还是有道理的。你觉得呢?
不过,python总是能够为我们着想的,它的指针提供了一个参数,可以实现将读取到的数据变成字典形式,这样就提供了另外一种读取方式了。
>>> cur = conn.cursor(cursorclass=mysqldb.cursors.dictcursor)
>>> cur.execute("select * from users")
7l
>>> cur.fetchall()
({'username': u'qiwsir', 'password': u'123123', 'id': 1l, 'email': }, {'username': u'mypython', 'password': u'123456', 'id': 2l, 'email': }, {'username': u'google', 'password': u'111222', 'id': 3l, 'email': }, {'username': u'facebook', 'password': u'222333', 'id': 4l, 'email': }, {'username': u'github', 'password': u'333444', 'id': 5l, 'email': }, {'username': u'docker', 'password': u'444555', 'id': 6l, 'email': }, {'username': u'\u8001\u9f50', 'password': u'9988', 'id': 7l, 'email': })
这样,在元组里面的元素就是一个一个字典。可以这样来操作这个对象:
>>> cur.scroll(0,"absolute")
>>> for line in cur.fetchall():
... print line["username"]
...
qiwsir
mypython
github
docker
老齐
根据字典对象的特点来读取了“键-值”。
更新数据
经过前面的操作,这个就比较简单了,不过需要提醒的是,如果更新完毕,和插入数据一样,都需要commit()来提交保存。
>>> cur.execute("update users set username=%s where id=2",("mypython"))
1l
>>> cur.execute("select * from users where id=2")
1l
>>> cur.fetchone()
(2l, u'mypython', u'123456', )
从操作中看出来了,已经将数据库中第二条的用户名修改为mypython了,用的就是update语句。
不过,要真的实现在数据库中更新,还要运行:
>>> conn.commit()
这就大事完吉了。