您的当前位置:首页正文

python中的MySQL数据库操作连接插入查询更新操作

2021-10-11 来源:客趣旅游网
python中的MySQL数据库操作连接插⼊查询更新操作

MySQL数据库

就数据库⽽⾔,连接之后就要对其操作。但是,⽬前那个名字叫做qiwsirtest的数据仅仅是空架⼦,没有什么可操作的,要操作它,就必须在⾥⾯建⽴“表”,什么是数据库的表呢?下⾯摘抄⾃维基百科对数据库表的简要解释,要想详细了解,需要看官在找⼀些有关数据库的教程和书籍来看看。

在关系数据库中,数据库表是⼀系列⼆维数组的集合,⽤来代表和储存数据对象之间的关系。它由纵向的列和横向的⾏组成,例如⼀个有关作者信息的名为 authors的表中,每个列包含的是所有作者的某个特定类型的信息,⽐如“姓⽒”,⽽每⾏则包含了某个特定作者的所有信息:姓、名、住址等等。

对于特定的数据库表,列的数⽬⼀般事先固定,各列之间可以由列名来识别。⽽⾏的数⽬可以随时、动态变化,每⾏通常都可以根据某个(或某⼏个)列中的数据来识别,称为候选键。

我打算在qiwsirtest中建⽴⼀个存储⽤户名、⽤户密码、⽤户邮箱的表,其结构⽤⼆维表格表现如下:usernamepasswordqiwsir

123123

emailqiwsir@gmail.com

特别说明,这⾥为了简化细节,突出重点,对密码不加密,直接明⽂保存,虽然这种⽅式是很不安全的。但是,有不少⽹站还都这么做的,这么做的⽬的是⽐较可恶的。就让我在这⾥,仅仅在这⾥可恶⼀次。

数据库表

因为直接操作数据部分,不是本教重点,但是关联到后⾯的操作,为了让读者在阅读上连贯,也快速地说明建⽴数据库表并输⼊内容。

mysql> use qiwsirtest;Database changedmysql> show tables;Empty set (0.00 sec)

⽤show tables命令显⽰这个数据库中是否有数据表了。查询结果显⽰为空。下⾯就⽤如下命令建⽴⼀个数据表,这个数据表的内容就是上⾯所说明的。

mysql> create table users(id int(2) not null primary key auto_increment,username varchar(40),password text,email text)default charset=utf8;Query OK, 0 rows affected (0.12 sec)

建⽴的这个数据表名称是:users,其中包含上述字段,可以⽤下⾯的⽅式看⼀看这个数据表的结构。

mysql> show tables;+----------------------+

| Tables_in_qiwsirtest |+----------------------+| users |+----------------------+1 row in set (0.00 sec)

查询显⽰,在qiwsirtest这个数据库中,已经有⼀个表,它的名字是:users。

mysql> desc users;

+----------+-------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |+----------+-------------+------+-----+---------+----------------+

| id | int(2) | NO | PRI | NULL | auto_increment || username | varchar(40) | YES | | NULL | || password | text | YES | | NULL | || email | text | YES | | NULL | |+----------+-------------+------+-----+---------+----------------+4 rows in set (0.00 sec)

显⽰表users的结构:

特别提醒:上述所有字段设置仅为演⽰,在实际开发中,要根据具体情况来确定字段的属性。如此就得到了⼀个空表。可以查询看看:

mysql> select * from users;Empty set (0.01 sec)

向⾥⾯插⼊点信息,就只插⼊⼀条吧。

mysql> insert into users(username,password,email) values(\"qiwsir\Query OK, 1 row affected (0.05 sec)mysql> select * from users;

+----+----------+----------+------------------+

| id | username | password | email |+----+----------+----------+------------------+

| 1 | qiwsir | 123123 | qiwsir@gmail.com |+----+----------+----------+------------------+1 row in set (0.00 sec)

这样就得到了⼀个有内容的数据库表。

python操作数据库

连接数据库,必须的。

>>> import MySQLdb

>>> conn = MySQLdb.connect(host=\"localhost\

Python建⽴了与数据的连接,其实是建⽴了⼀个MySQLdb.connect()的实例对象,或者泛泛地称之为连接对象,python就是通过连接对象和数据库对话。这个对象常⽤的⽅法有:

commit():如果数据库表进⾏了修改,提交保存当前的数据。当然,如果此⽤户没有权限就作罢了,什么也不会发⽣。rollback():如果有权限,就取消当前的操作,否则报错。

cursor([cursorclass]):返回连接的游标对象。通过游标执⾏SQL查询并检查结果。游标⽐连接⽀持更多的⽅法,⽽且可能在程序中更好⽤。close():关闭连接。此后,连接对象和游标都不再可⽤了。

Python和数据之间的连接建⽴起来之后,要操作数据库,就需要让python对数据库执⾏SQL语句。Python是通过游标执⾏SQL语句的。所以,连接建⽴之后,就要利⽤连接对象得到游标对象,⽅法如下:

>>> cur = conn.cursor()

此后,就可以利⽤游标对象的⽅法对数据库进⾏操作。那么还得了解游标对象的常⽤⽅法:

名称

close()

关闭游标。之后游标不可⽤

描述

execute(query[,args])执⾏⼀条SQL语句,可以带参数名称

executemany(query, pseq)对序列pseq中的每个参数执⾏sql语句fetchone()fetchall()fetchmany([size])nextset()

返回⼀条查询结果返回所有查询结果返回size条结果移动到下⼀个结果

描述

scroll(value,mode='relative')移动游标到指定⾏,如果mode='relative',则表⽰从当前所在⾏移动value条,如果mode='absolute',则表⽰从结果集的第⼀⾏移动value条.

插⼊

例如,要在数据表users中插⼊⼀条记录,使得:username=\"python\,这样做:

>>> cur.execute(\"insert into users (username,password,email) values (%s,%s,%s)\1L

没有报错,并且返回⼀个\"1L\"结果,说明有⼀⾏记录操作成功。不妨⽤\"mysql>\"交互⽅式查看⼀下:

mysql> select * from users;

+----+----------+----------+------------------+

| id | username | password | email |+----+----------+----------+------------------+

| 1 | qiwsir | 123123 | qiwsir@gmail.com |+----+----------+----------+------------------+1 row in set (0.00 sec)

咦,奇怪呀。怎么没有看到增加的那⼀条呢?哪⾥错了?可是上⾯也没有报错呀。

特别注意,通过\"cur.execute()\"对数据库进⾏操作之后,没有报错,完全正确,但是不等于数据就已经提交到数据库中了,还必须要⽤到\"MySQLdb.connect\"的⼀个属性:commit(),将数据提交上去,也就是进⾏了\"cur.execute()\"操作,要将数据提交,必须执⾏:

>>> conn.commit()

再到\"mysql>\"中运⾏\"select * from users\"试⼀试:

mysql> select * from users;

+----+----------+----------+------------------+

| id | username | password | email |+----+----------+----------+------------------+

| 1 | qiwsir | 123123 | qiwsir@gmail.com || 2 | python | 123456 | python@gmail.com |+----+----------+----------+------------------+2 rows in set (0.00 sec)

果然如此。这就如同编写⼀个⽂本⼀样,将⽂字写到⽂本上,并不等于⽂字已经保留在⽂本⽂件中了,必须执⾏\"CTRL-S\"才能保存。也就是在通过python操作数据库的时候,以\"execute()\"执⾏各种sql语句之后,要让已经执⾏的效果保存,必须运⾏连接对象的\"commit()\"⽅法。再尝试⼀下插⼊多条的那个命令\"executemany(query,args)\".

>>> cur.executemany(\"insert into users (username,password,email) values (%s,%s,%s)\4L

>>> conn.commit()

到\"mysql>\"⾥⾯看结果:

mysql> select * from users;

+----+----------+----------+------------------+

| id | username | password | email |+----+----------+----------+------------------+

| 1 | qiwsir | 123123 | qiwsir@gmail.com || 2 | python | 123456 | python@gmail.com || 3 | google | 111222 | g@gmail.com || 4 | facebook | 222333 | f@face.book || 5 | github | 333444 | git@hub.com || 6 | docker | 444555 | doc@ker.com |+----+----------+----------+------------------+6 rows in set (0.00 sec)

成功插⼊了多条记录。在\"executemany(query, pseq)\"中,query还是⼀条sql语句,但是pseq这时候是⼀个tuple,这个tuple⾥⾯的元素也是tuple,每个tuple分别对应sql语句中的字段列表。这句话其实被执⾏多次。只不过执⾏过程不显⽰给我们看罢了。除了插⼊命令,其它对数据操作的命了都可⽤类似上⾯的⽅式,⽐如删除、修改等。

查询

如果要从数据库中查询数据,也⽤游标⽅法来操作了。

>>> cur.execute(\"select * from users\") 7L

这说明从users表汇总查询出来了7条记录。但是,这似乎有点不友好,告诉我7条记录查出来了,但是在哪⾥呢,如果在'mysql>'下操作查询命令,⼀下就把7条记录列出来了。怎么显⽰python在这⾥的查询结果呢?

要⽤到游标对象的fetchall()、fetchmany(size=None)、fetchone()、scroll(value, mode='relative')等⽅法。

>>> cur.execute(\"select * from users\") 7L

>>> lines = cur.fetchall()

到这⾥,已经将查询到的记录赋值给变量lines了。如果要把它们显⽰出来,就要⽤到曾经学习过的循环语句了。

>>> for line in lines:... print line...

(1L, u'qiwsir', u'123123', u'qiwsir@gmail.com')(2L, u'python', u'123456', u'python@gmail.com')(3L, u'google', u'111222', u'g@gmail.com')(4L, u'facebook', u'222333', u'f@face.book')(5L, u'github', u'333444', u'git@hub.com')(6L, u'docker', u'444555', u'doc@ker.com')

(7L, u'\老\齐', u'9988', u'qiwsir@gmail.com')

很好。果然是逐条显⽰出来了。列位注意,第七条中的u'\老\闵',这⾥是汉字,只不过由于我的shell不能显⽰罢了,不必惊慌,不必搭理它。只想查出第⼀条,可以吗?当然可以!看下⾯的:

>>> cur.execute(\"select * from users where id=1\")1L

>>> line_first = cur.fetchone() #只返回⼀条>>> print line_first

(1L, u'qiwsir', u'123123', u'qiwsir@gmail.com')

为了对上述过程了解深⼊,做下⾯实验:

>>> cur.execute(\"select * from users\")7L

>>> print cur.fetchall()

((1L, u'qiwsir', u'123123', u'qiwsir@gmail.com'), (2L, u'python', u'123456', u'python@gmail.com'), (3L, u'google', u'111222', u'g@gmail.com'), (4L, u'facebook', u'222333', u'f@face.book'), (5L, u'github', u'333444', u'git@hub.com'), (6L, u'docker',

原来,⽤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', u'qiwsir@gmail.com')>>> print cur.fetchone()

(2L, u'python', u'123456', u'python@gmail.com')>>> print cur.fetchone()

(3L, u'google', u'111222', u'g@gmail.com')

这次我不⼀次全部打印出来了,⽽是⼀次打印⼀条,看官可以从结果中看出来,果然那个游标在⼀条⼀条向下移动呢。注意,我在这次实验中,是重新运⾏了查询语句。那么,既然在操作存储在内存中的对象时候,游标会移动,能不能让游标向上移动,或者移动到指定位置呢?这就是那个scroll()

>>> cur.scroll(1)

>>> print cur.fetchone()

(5L, u'github', u'333444', u'git@hub.com')>>> cur.scroll(-2)

>>> print cur.fetchone()

(4L, u'facebook', u'222333', u'f@face.book')

果然,这个函数能够移动游标,不过请仔细观察,上⾯的⽅式是让游标相对与当前位置向上或者向下移动。即:

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', u'g@gmail.com')>>> cur.scroll(1,\"absolute\")>>> print cur.fetchone()

(2L, u'python', u'123456', u'python@gmail.com')

>>> cur.scroll(0,\"absolute\") #回到序号是0,即指向tuple的第⼀条>>> print cur.fetchone()

(1L, u'qiwsir', u'123123', u'qiwsir@gmail.com')

⾄此,已经熟悉了cur.fetchall()和cur.fetchone()以及cur.scroll()⼏个⽅法,还有另外⼀个,接这上边的操作,也就是游标在序号是1的位置,指向了tuple的第⼆条

>>> cur.fetchmany(3)

((2L, u'python', u'123456', u'python@gmail.com'), (3L, u'google', u'111222', u'g@gmail.com'), (4L, u'facebook', u'222333', u'f@face.book'))

上⾯这个操作,就是实现了从当前位置(游标指向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': u'qiwsir@gmail.com'}, {'username': u'mypython', 'password': u'123456', 'id': 2L, 'email': u'python@gmail.com'}, {'username': u'google', 'password': u'111222', 'id': 3L, 'email': u'g@gmail.com'},

这样,在元组⾥⾯的元素就是⼀个⼀个字典:

>>> cur.scroll(0,\"absolute\")>>> for line in cur.fetchall():... print line[\"username\"]... qiwsirmypythongooglefacebookgithubdocker⽼齐

根据字典对象的特点来读取了“键-值”。

更新数据

经过前⾯的操作,这个就⽐较简单了,不过需要提醒的是,如果更新完毕,和插⼊数据⼀样,都需要commit()来提交保存。

>>> cur.execute(\"update users set username=%s where id=2\1L

>>> cur.execute(\"select * from users where id=2\")1L

>>> cur.fetchone()

(2L, u'mypython', u'123456', u'python@gmail.com')

从操作中看出来了,已经将数据库中第⼆条的⽤户名修改为mypython了,⽤的就是update语句。不过,要真的实现在数据库中更新,还要运⾏:

>>> conn.commit()

这就⼤事完吉了。

应该还有个⼩尾巴,那就是当你操作数据完毕,不要忘记关门:

>>> cur.close()>>> conn.close()

转载⾃《零基础学python》(第⼆版)

因篇幅问题不能全部显示,请点此查看更多更全内容