python mysqldb 教程

 

[ruby] 
view plain
 copy  

    1. MySQL Python 教程  
    2.   
    3. (1)下面是在Python中使用MySql数据库的教程,涵盖了Python对MySql的基础操作,主要采用了MySQLdb模块,下面的代码都是基于Ubuntu Linux测试的。  
    4.   
    5. (2)MySQL 数据库  
    6.   
    7. MySQL是一套领先的开源的数据库管理系统,它是多用户,多线程的数据库系统,尤其是是在web领域非常著名,它是非常流行的LAMP的一部分, Linux, Apache, MySQL, PHP。当前,MySQL已经归属为Oracle,MySQL可以有效的运行在各个操作系统平台上, BSD Unix, Linux, Windows or Mac.  Wikipedia 和 YouTube 业主使用MySQL,这些站点每天都支撑着数以亿计的查询,MySQL来源于MySQL server system 和MySQL embedded system.  
    8.   
    9. (3)准备工作  
    10.   
    11. 首先要安装一些软件包,应用于我们接下来的工作。  
    12.   
    13. #  
    14. sudo apt-get install mysql-server  
    15.   
    16. 上面的命令用于安装 mysql-server,在这个过程中会弹出提示要求输入管理员密码。  
    17. 安装mysql以后,来安装mysql的python模块,  
    18.   
    19. #  
    20. apt-cache search MySQLdb  
    21.   
    22. 如果不知道 MySQLdb 对于 Python 的模块,可以搜索下 MySQLdb,类似会有如下的信息  
    23.   
    24. python-mysqldb – A Python interface to MySQL  
    25. python-mysqldb-dbg – A Python interface to MySQL (debug extension)  
    26. bibus – bibliographic database  
    27. eikazo – graphical frontend for SANE designed for mass-scanning  
    28.   
    29. 接下来是安装 python-mysqldb  
    30.   
    31. #  
    32. apt-get install python-mysqldb  
    33.   
    34. 这样我们就安装了 python 访问 mysql 的接口,包含了 _mysql 和 MySQLdb 这两个模块。  
    35.   
    36. 下面我们用 mysql 的客户端来创建一个用户和一个数据库  
    37.   
    38. #  
    39. mysql -u root -p  
    40.   
    41. Enter password: 此处会要求输入密码  
    42.   
    43. Welcome to the MySQL monitor.  Commands end with ; or \g.  
    44. Your MySQL connection id is 30  
    45. Server version: 5.0.67-0ubuntu6 (Ubuntu)  
    46.   
    47. Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.  
    48.   
    49. mysql> SHOW DATABASES;  
    50. +——————–+  
    51. | Database           |  
    52. +——————–+  
    53. | information_schema |   
    54. | mysql              |   
    55. +——————–+  
    56. 2 rows in set (0.00 sec)  
    57.   
    58. 已经用root帐号登录了数据库,接下来创建一个数据库  
    59.   
    60. mysql> CREATE DATABASE testdb;  
    61. Query OK, 1 row affected (0.02 sec)  
    62.   
    63. 我们创建了一个叫 testdb 的数据库,在这个教程中,我们将使用此数据库。  
    64.   
    65. mysql> CREATE USER ‘testuser’@‘localhost’ IDENTIFIED BY ‘test623’;  
    66. Query OK, 0 rows affected (0.00 sec)  
    67.   
    68. 为此数据库添加一个可访问的用户,用户名是 testuser,密码是 test623,并且给该用户授予了这个数据所有的操作权限  
    69.   
    70. mysql> USE testdb;  
    71. Database changed  
    72.   
    73. mysql> GRANT ALL ON testdb.* TO ‘testuser’@‘localhost’;  
    74. Query OK, 0 rows affected (0.00 sec)  
    75.   
    76. mysql> quit;  
    77.   
    78. 退出  
    79.   
    80. (4)_mysql 模块  
    81.   
    82. _mysql 模块直接实现了MYSQL C API,它不兼容 Python DB API,一般情况下,程序员喜欢 MySQLdb 模块,稍候我们在介绍 MySQLdb 模块,我们先来看下 _mysql 的小例子  
    83.   
    84. #!/usr/bin/python  
    85. # -*- coding: utf-8 -*-  
    86.   
    87. import _mysql  
    88. import sys  
    89.   
    90.   
    91. con = None  
    92.   
    93. try:  
    94.   
    95.     con = _mysql.connect(‘localhost’, ‘testuser’,   
    96.         ‘test623’, ‘testdb’)  
    97.           
    98.     con.query(“SELECT VERSION()”)  
    99.     result = con.use_result()  
    100.       
    101.     print “MySQL version: %s” % \  
    102.         result.fetch_row()[0]  
    103.       
    104. except _mysql.Error, e:  
    105.     
    106.     print “Error %d: %s” % (e.args[0], e.args[1])  
    107.     sys.exit(1)  
    108.   
    109. finally:  
    110.       
    111.     if con:  
    112.         con.close()  
    113.   
    114. 上面这个例子展示了通过 _mysql 模块,获得数据库版本的一段代码。并且用了  SELECT VERSION() 这个语句。  
    115.   
    116. (5)MySQLdb 模块  
    117.   
    118. MySQLdb 是对 _mysql 的一个轻量级的包装。兼容了 Python DB API,让代码更加便捷,利用该模块与 mysql 一起是首选。  
    119.   
    120. 1、 获得数据的版本  
    121.   
    122. #!/usr/bin/python  
    123. # -*- coding: utf-8 -*-  
    124.   
    125. import MySQLdb as mdb  
    126. import sys  
    127.   
    128. con = None  
    129.   
    130. try:  
    131.   
    132.     con = mdb.connect(‘localhost’, ‘testuser’,   
    133.         ‘test623’, ‘testdb’);  
    134.   
    135.     cur = con.cursor()  
    136.     cur.execute(“SELECT VERSION()”)  
    137.   
    138.     data = cur.fetchone()  
    139.       
    140.     print “Database version : %s ” % data  
    141.       
    142. except mdb.Error, e:  
    143.     
    144.     print “Error %d: %s” % (e.args[0],e.args[1])  
    145.     sys.exit(1)  
    146.       
    147. finally:      
    148.           
    149.     if con:      
    150.         con.close()  
    151.   
    152. 在这个例子中,我们连接了 testdb 数据库,并且执行了 SELECT VERSION() 这个语句,并且返回了数据的版本,把它输出显示在屏幕上。  
    153.   
    154. #  
    155. import MySQLdb as mdb  
    156.   
    157. import 模块 MySQLdb  
    158.   
    159. #  
    160. con = None  
    161.   
    162. 初始化变量 con, 并且赋值为 None  
    163. 在有些情况下,我们可能不能创建一个连接去连接数据库,例如磁盘满了的情况下,那么我们没有连接被定义,这样将会在 finally 语句中产生错误。  
    164.   
    165. #  
    166. con = mdb.connect(‘localhost’, ‘testuser’,   
    167.     ‘test623’, ‘testdb’);  
    168.   
    169. 连接数据库,在这里 mdb 是 MySQLdb 的别名,在开始 import 模块的时候命名的,connect 方法有四个参数,第一个是数据库的地址,第二个是用户名,第三个是密码,第四个是要访问的数据库名称。  
    170.   
    171. #  
    172. cur = con.cursor()  
    173. cur.execute(“SELECT VERSION()”)  
    174.   
    175. 从 con 我们获得了 cursor 对象,该对象用于从结果集(result set)中萃取记录,最后我们调用了改对象的 execute 方法来执行 SQL 语句。  
    176.   
    177. #  
    178. data = cur.fetchone()  
    179.   
    180. 获取了一条记录,采用 fetchone 这个方法。  
    181.   
    182. #  
    183. print “Database version : %s ” % data  
    184.   
    185. 将我们获取的数据输出  
    186.   
    187. #  
    188. except mdb.Error, e:  
    189.     
    190.     print “Error %d: %s” % (e.args[0],e.args[1])  
    191.     sys.exit(1)  
    192.   
    193. 一旦数据库发生了错误,那么捕获错误是非常重要的。  
    194.   
    195. #  
    196. finally:      
    197.           
    198.     if con:      
    199.         con.close()  
    200.   
    201. 最后,释放资源  
    202.   
    203. 2、创建一个表,并且填充数据  
    204.   
    205. #!/usr/bin/python  
    206. # -*- coding: utf-8 -*-  
    207.   
    208. import MySQLdb as mdb  
    209. import sys  
    210.   
    211. con = mdb.connect(‘localhost’, ‘testuser’, ‘test623’, ‘testdb’);  
    212.   
    213. with con:  
    214.       
    215.     cur = con.cursor()  
    216.     cur.execute(“CREATE TABLE IF NOT EXISTS \  
    217.         Writers(Id INT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(25))”)  
    218.     cur.execute(“INSERT INTO Writers(Name) VALUES(‘Jack London’)”)  
    219.     cur.execute(“INSERT INTO Writers(Name) VALUES(‘Honore de Balzac’)”)  
    220.     cur.execute(“INSERT INTO Writers(Name) VALUES(‘Lion Feuchtwanger’)”)  
    221.     cur.execute(“INSERT INTO Writers(Name) VALUES(‘Emile Zola’)”)  
    222.     cur.execute(“INSERT INTO Writers(Name) VALUES(‘Truman Capote’)”)  
    223.   
    224. 我们创建了一个表,并且添加了五条记录  
    225.   
    226. #  
    227. cur.execute(“CREATE TABLE IF NOT EXISTS \  
    228.     Writers(Id INT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(25))”)  
    229.   
    230. 这个语句创建了一个数据表叫 Writers,该表有两列 ID 和 Name  
    231.   
    232. #  
    233. cur.execute(“INSERT INTO Writers(Name) VALUES(‘Jack London’)”)  
    234. cur.execute(“INSERT INTO Writers(Name) VALUES(‘Honore de Balzac’)”)  
    235. ……  
    236.   
    237. 向数据表插入数据。  
    238.   
    239. #  
    240. mysql> SELECT * FROM Writers;  
    241. +—-+——————-+  
    242. | Id | Name              |  
    243. +—-+——————-+  
    244. |  1 | Jack London       |  
    245. |  2 | Honore de Balzac  |  
    246. |  3 | Lion Feuchtwanger |  
    247. |  4 | Emile Zola        |  
    248. |  5 | Truman Capote     |  
    249. +—-+——————-+  
    250. 5 rows in set (0.00 sec)  
    251.   
    252. 下面可以通过 mysql 命令行工具,来查看下当前数据表中的数据  
    253.   
    254. 3、获取数据(retrieving data)  
    255.   
    256. 上面的例子中,我们已经向表中添加了一些数据,下面我们把他们取出来  
    257.   
    258. #!/usr/bin/python  
    259. # -*- coding: utf-8 -*-  
    260.   
    261. import MySQLdb as mdb  
    262. import sys  
    263.   
    264.   
    265. con = mdb.connect(‘localhost’, ‘testuser’,   
    266.         ‘test623’, ‘testdb’);  
    267.   
    268. with con:   
    269.   
    270.     cur = con.cursor()  
    271.     cur.execute(“SELECT * FROM Writers”)  
    272.   
    273.     rows = cur.fetchall()  
    274.   
    275.     for row in rows:  
    276.         print row  
    277.   
    278. 在上面的代码中,我们取出来所有的数据  
    279.   
    280. #  
    281. cur.execute(“SELECT * FROM Writers”)  
    282.   
    283. 这个语句检索了 Writers 表中所有的数据  
    284.   
    285. #  
    286. rows = cur.fetchall()  
    287.   
    288. fetchall 方法获得了所有的记录,返回了一个结果集,技术上是返回了一个由元组组成的元组,这个结合中每一个元组就是一行记录。  
    289.   
    290. #  
    291. for row in rows:  
    292.     print row  
    293.   
    294. 一行一行的将数据打印出来  
    295.   
    296. $ ./retrieve.py  
    297. (1L, ‘Jack London’)  
    298. (2L, ‘Honore de Balzac’)  
    299. (3L, ‘Lion Feuchtwanger’)  
    300. (4L, ‘Emile Zola’)  
    301. (5L, ‘Truman Capote’)  
    302.   
    303. 4、有时候一次取出全部数据并不可取,我们可以一行一行的来取出,下面这个例子就是  
    304.   
    305. #!/usr/bin/python  
    306. # -*- coding: utf-8 -*-  
    307.   
    308. import MySQLdb as mdb  
    309. import sys  
    310.   
    311.   
    312. con = mdb.connect(‘localhost’, ‘testuser’,   
    313.     ‘test623’, ‘testdb’);  
    314.   
    315. with con:  
    316.   
    317.     cur = con.cursor()  
    318.     cur.execute(“SELECT * FROM Writers”)  
    319.   
    320.     numrows = int(cur.rowcount)  
    321.   
    322.     for i in range(numrows):  
    323.         row = cur.fetchone()  
    324.         print row[0], row[1]  
    325.   
    326. 我们还是和第3个例子一样,取出表中数据并输出,这次我们并没有采用 fetchall 方法,而是一步一步的取出来。  
    327.   
    328. #  
    329. numrows = int(cur.rowcount)  
    330.   
    331. 获得返回结果集的记录数量  
    332.   
    333. #  
    334. for i in range(numrows):  
    335.     row = cur.fetchone()  
    336.     print row[0], row[1]  
    337.   
    338. 通过 fetchone 来一步一步的取出数据,结果如下  
    339.   
    340. $ ./retrieve2.py  
    341. 1 Jack London  
    342. 2 Honore de Balzac  
    343. 3 Lion Feuchtwanger  
    344. 4 Emile Zola  
    345. 5 Truman Capote  
    346.   
    347. 5、The dictionary cursor (这个我也不知道怎么翻译好,姑且翻译为 字典型游标 吧)  
    348.   
    349. 在 MySQLdb 里有多种 游标(cursor) 类型,默认返回的是由元组构成的元组,如果我们采用西典型游标,数据将会以字典的形式返回,这样返回的数据可以关联到数据库表的字段名  
    350.   
    351. #!/usr/bin/python  
    352. # -*- coding: utf-8 -*-  
    353.   
    354. import MySQLdb as mdb  
    355. import sys  
    356.   
    357. con = mdb.connect(‘localhost’, ‘testuser’,   
    358.     ‘test623’, ‘testdb’)  
    359.   
    360. with con:  
    361.   
    362.     cur = con.cursor(mdb.cursors.DictCursor)  
    363.     cur.execute(“SELECT * FROM Writers”)  
    364.   
    365.     rows = cur.fetchall()  
    366.   
    367.     for row in rows:  
    368.         print “%s %s” % (row[“Id”], row[“Name”])  
    369.   
    370. 上面这个例子里,我们用来 字典型游标 来打印结果  
    371.   
    372. #  
    373. cur = con.cursor(mdb.cursors.DictCursor)  
    374.   
    375. 使用 字典型游标  
    376.   
    377. #  
    378. rows = cur.fetchall()  
    379.   
    380. 获取所有的结果  
    381.   
    382. #  
    383. for row in rows:  
    384.         print “%s %s” % (row[“Id”], row[“Name”])  
    385.   
    386. 关联到字段名称输出  
    387.   
    388. 6、Column headers  
    389.   
    390. 接下来的例子是通过 Column headers 的方式来从数据表中输出数据  
    391.   
    392. #!/usr/bin/python  
    393. # -*- coding: utf-8 -*-  
    394.   
    395. import MySQLdb as mdb  
    396. import sys  
    397.   
    398.   
    399. con = mdb.connect(‘localhost’, ‘testuser’,   
    400.     ‘test623’, ‘testdb’)  
    401.   
    402. with con:  
    403.   
    404.     cur = con.cursor()  
    405.     cur.execute(“SELECT * FROM Writers”)  
    406.   
    407.     rows = cur.fetchall()  
    408.   
    409.     desc = cur.description  
    410.   
    411.     print “%s %3s” % (desc[0][0], desc[1][0])  
    412.   
    413.     for row in rows:      
    414.         print “%2s %3s” % row  
    415.   
    416. 我们还是把整个表的数据输出出来,现在我们也包含了列的名字,列明被认为是 “meta data”,也是可以通过 cursor 对象获得的。  
    417.   
    418. #  
    419. desc = cur.description  
    420.   
    421. 这个 cursor对象的[描述属性]返回了每个查询结果集列的信息。  
    422.   
    423. #  
    424. print “%s %3s” % (desc[0][0], desc[1][0])  
    425.   
    426. 打印并且格式化列明信息  
    427.   
    428. #  
    429. for row in rows:      
    430.     print “%2s %3s” % row  
    431.   
    432. 打印数据  
    433.   
    434. $ ./columnheaders.py  
    435. Id Name  
    436.  1 Jack London  
    437.  2 Honore de Balzac  
    438.  3 Lion Feuchtwanger  
    439.  4 Emile Zola  
    440.  5 Truman Capote  
    441.   
    442. 7、Prepared statements (预编译语句?)  
    443.   
    444. 现在我们要来关注 prepared statements ,我们用占位符来替换一些语句中的变量,prepared statements 方式提高了性能和安全性,PYTHON DB API 规定了五种不同的方式来构建 prepared statements。MySQLdb 支持了其中的一种,ANSI printf format  
    445.   
    446. #!/usr/bin/python  
    447. # -*- coding: utf-8 -*-  
    448.   
    449. import MySQLdb as mdb  
    450. import sys  
    451.   
    452.   
    453. con = mdb.connect(‘localhost’, ‘testuser’,   
    454.     ‘test623’, ‘testdb’)  
    455.       
    456. with con:      
    457.   
    458.     cur = con.cursor()  
    459.           
    460.     cur.execute(“UPDATE Writers SET Name = %s WHERE Id = %s”,   
    461.         (“Guy de Maupasant”, “4”))          
    462.       
    463.     print “Number of rows updated: %d” % cur.rowcount  
    464.   
    465. 我们通过ID改变数据库记录中一个人的名字  
    466.   
    467. #  
    468. cur.execute(“UPDATE Writers SET Name = %s WHERE Id = %s”,   
    469.     (“Guy de Maupasant”, “4”))     
    470.      
    471. %s 就是占位符  
    472.   
    473. mysql> SELECT Name FROM Writers WHERE Id=4;  
    474. +——————+  
    475. | Name             |  
    476. +——————+  
    477. | Guy de Maupasant |  
    478. +——————+  
    479. 1 row in set (0.00 sec)  
    480.   
    481. 名字被成功的改写了。  
    482.   
    483. 8、写图片  
    484.   
    485. 有的人喜欢把图片存储到数据库中,有的人喜欢把图片存储在文件系统中,MYSQL 有一种数据类型就是用于存储二进制数据的,叫 BLOB  
    486.   
    487. #  
    488. mysql> CREATE TABLE Images(Id INT PRIMARY KEY AUTO_INCREMENT, Data MEDIUMBLOB);  
    489. Query OK, 0 rows affected (0.06 sec)  
    490.   
    491. 这个例子,我们创建一个表叫 images  
    492.   
    493. #!/usr/bin/python  
    494. # -*- coding: utf-8 -*-  
    495.   
    496. import MySQLdb as mdb  
    497. import sys  
    498.   
    499. try:  
    500.     fin = open(“chrome.png”)  
    501.     img = fin.read()  
    502.     fin.close()  
    503.   
    504. except IOError, e:  
    505.   
    506.     print “Error %d: %s” % (e.args[0],e.args[1])  
    507.     sys.exit(1)  
    508.   
    509.    
    510. try:  
    511.     conn = mdb.connect(host=‘localhost’,user=‘testuser’,  
    512.        passwd=‘test623’, db=‘testdb’)  
    513.     cursor = conn.cursor()  
    514.     cursor.execute(“INSERT INTO Images SET Data=’%s'” % \  
    515.         mdb.escape_string(img))  
    516.   
    517.     conn.commit()  
    518.   
    519.     cursor.close()  
    520.     conn.close()  
    521.   
    522. except mdb.Error, e:  
    523.     
    524.     print “Error %d: %s” % (e.args[0],e.args[1])  
    525.     sys.exit(1)  
    526.   
    527. 上面的例子中,我们读取了一个图片,并且存储到了表中。  
    528.   
    529. #  
    530. fin = open(“chrome.png”)  
    531. img = fin.read()  
    532.   
    533. 打开并且读取图片, read 方法返回一个字符串  
    534.   
    535. #  
    536. cursor.execute(“INSERT INTO Images SET Data=’%s'” % \  
    537.     mdb.escape_string(img))  
    538.   
    539. 将字符串插入到表中,在这个语句中调用了  escape_string() 方法,主要是为了方式 SQL 注入  
    540.   
    541. 9、读取图片  
    542.   
    543. 在前面的例子中,我们已经插入了一个图片到数据表中,下面将读取图片  
    544.   
    545. #!/usr/bin/python  
    546. # -*- coding: utf-8 -*-  
    547.   
    548. import MySQLdb as mdb   
    549. import sys  
    550.   
    551. try:  
    552.     conn = mdb.connect(host=‘localhost’,user=‘testuser’,   
    553.         passwd=‘test623’, db=‘testdb’)  
    554.   
    555.     cursor = conn.cursor()  
    556.   
    557.     cursor.execute(“SELECT Data FROM Images LIMIT 1”)  
    558.   
    559.     fout = open(‘image.png’,‘wb’)  
    560.     fout.write(cursor.fetchone()[0])  
    561.     fout.close()  
    562.   
    563.     cursor.close()  
    564.     conn.close()  
    565.   
    566. except IOError, e:  
    567.   
    568.     print “Error %d: %s” % (e.args[0],e.args[1])  
    569.     sys.exit(1)  
    570.   
    571. 从数据表中读取图片  
    572.   
    573. #  
    574. cursor.execute(“SELECT Data FROM Images LIMIT 1”)  
    575.   
    576. 从数据库表中查询一条记录  
    577.   
    578. #  
    579. fout = open(‘image.png’,‘wb’)  
    580.   
    581. 打开一个可写入状态的二进制文件  
    582.   
    583. #  
    584. fout.write(cursor.fetchone()[0])  
    585.   
    586. 写入数据  
    587.   
    588. 现在就可以看到当前的目录下多了一个 image.png 文件  
    589.   
    590. 10、事务支持  
    591.   
    592. 事务是数据库操作的一个原子单元,它影响的是数据库操作的一组记录,整体提交或者整体回滚,如果一个一组中的一个操作失败,那么就是整体回滚。MYSQL 中 MYISAM 引擎不支持事务操作,InnoDB 引擎支持事务操作。  
    593.   
    594. #!/usr/bin/python  
    595. # -*- coding: utf-8 -*-  
    596.   
    597. import MySQLdb as mdb  
    598. import sys  
    599.   
    600. try:  
    601.     conn = mdb.connect(‘localhost’, ‘testuser’,   
    602.         ‘test623’, ‘testdb’);  
    603.   
    604.     cursor = conn.cursor()  
    605.       
    606.     cursor.execute(“UPDATE Writers SET Name = %s WHERE Id = %s”,   
    607.         (“Leo Tolstoy”, “1”))         
    608.     cursor.execute(“UPDATE Writers SET Name = %s WHERE Id = %s”,   
    609.         (“Boris Pasternak”, “2”))  
    610.     cursor.execute(“UPDATE Writer SET Name = %s WHERE Id = %s”,   
    611.         (“Leonid Leonov”, “3”))     
    612.   
    613.     conn.commit()  
    614.   
    615.     cursor.close()  
    616.     conn.close()  
    617.   
    618. except mdb.Error, e:  
    619.     
    620.     conn.rollback()  
    621.     print “Error %d: %s” % (e.args[0],e.args[1])  
    622.     sys.exit(1)  
    623.   
    624. 这个例子中,我们尝试更新三个记录,数据表的引擎是 MyISAM  
    625.   
    626. #  
    627. cursor.execute(“UPDATE Writers SET Name = %s WHERE Id = %s”,   
    628.     (“Leo Tolstoy”, “1”))         
    629. cursor.execute(“UPDATE Writers SET Name = %s WHERE Id = %s”,   
    630.     (“Boris Pasternak”, “2”))  
    631.   
    632. 将两个ID分别为1和2的记录换Name  
    633.   
    634. #  
    635. cursor.execute(“UPDATE Writer SET Name = %s WHERE Id = %s”,   
    636.     (“Leonid Leonov”, “3”))     
    637.   
    638. 这是一个错误的语句,表名不是 Writers ,少了一个 s,  
    639.   
    640. #  
    641. conn.rollback()    
    642.   
    643. 调用了 rollback 方法,但是并没有触发回滚操作,下面来看下操作结果  
    644.   
    645. Error 1146: Table ‘testdb.Writer’ doesn’t exist  
    646.   
    647. mysql> SELECT * FROM Writers;  
    648. +—-+——————-+  
    649. | Id | Name              |  
    650. +—-+——————-+  
    651. |  1 | Leo Tolstoy       |  
    652. |  2 | Boris Pasternak   |  
    653. |  3 | Lion Feuchtwanger |  
    654. |  4 | Guy de Maupasant  |  
    655. |  5 | Truman Capote     |  
    656. +—-+——————-+  
    657. 5 rows in set (0.00 sec)  
    658.   
    659. 报了一个错误,但是结果已经被改变了,并没有执行回滚操作。  
    660.   
    661.   
    662. 最后一个例子里,我们来创建一个新的 writers 表,为 InnoDB 引擎,支持事务。  
    663.   
    664. DROP TABLE Writers;  
    665.   
    666. CREATE TABLE IF NOT EXISTS Writers(Id INT PRIMARY KEY AUTO_INCREMENT,   
    667.     Name VARCHAR(25)) ENGINE=INNODB;  
    668.   
    669. INSERT INTO Writers(Name) VALUES(‘Jack London’);  
    670. INSERT INTO Writers(Name) VALUES(‘Honore de Balzac’);  
    671. INSERT INTO Writers(Name) VALUES(‘Lion Feuchtwanger’);  
    672. INSERT INTO Writers(Name) VALUES(‘Emile Zola’);  
    673. INSERT INTO Writers(Name) VALUES(‘Truman Capote’);  
    674.   
    675. 来看下下面的脚本  
    676.   
    677. #!/usr/bin/python  
    678. # -*- coding: utf-8 -*-  
    679.   
    680. import MySQLdb as mdb  
    681. import sys  
    682.   
    683. try:  
    684.     conn = mdb.connect(‘localhost’, ‘testuser’,   
    685.         ‘test623’, ‘testdb’);  
    686.   
    687.     cursor = conn.cursor()  
    688.       
    689.     cursor.execute(“DELETE FROM Writers WHERE Id = 5”)    
    690.     cursor.execute(“DELETE FROM Writers WHERE Id = 4”)   
    691.     cursor.execute(“DELETE FROM Writer WHERE Id = 3”)   
    692.       
    693.     conn.commit()  
    694.   
    695. except mdb.Error, e:  
    696.     
    697.     conn.rollback()  
    698.     print “Error %d: %s” % (e.args[0],e.args[1])  
    699.     sys.exit(1)  
    700.   
    701. cursor.close()  
    702. conn.close()  
    703.   
    704. 执行上面的脚本,删除三条记录,但是第三条语句是错误的。所以执行了数据库回滚的操作,来看下最终的结果集  
    705.   
    706. Error 1146: Table ‘testdb.Writer’ doesn’t exist  
    707.   
    708. mysql> SELECT * FROM Writers;  
    709. +—-+——————-+  
    710. | Id | Name              |  
    711. +—-+——————-+  
    712. |  1 | Jack London       |  
    713. |  2 | Honore de Balzac  |  
    714. |  3 | Lion Feuchtwanger |  
    715. |  4 | Emile Zola        |  
    716. |  5 | Truman Capote     |  
    717. +—-+——————-+  
    718. 5 rows in set (0.00 sec)  
    719.   
    720. (完)  
点赞