[每日一题]20、Python操作MySQL

点击上方Python3X”,选择“置顶或者星标

第一时间收到精彩推送!


Python Every Day, 第 20 天


     在工作中,不管Web开发或者爬虫,数据分析等凡是与数据有接触的都离不开数据库。数据库又分为关系型数据库还是非关系型数据库,关系型数据库中最常用应该就是MySQL了。


在Python中可以通过PyMySQL库完成对其的操作。


安装PyMySQL


 
 
pip3 install pymysql


操作过程大概分为如下几步

0、在MySQL中创建库和表 1、创建数据库连接 2、创建cursor,用于执行sql 3、编写并执行SQL 4、获取数据 5、关闭连接


通过下面一个简单的例子给大家演示一下

创建test库,并在该库中创建fund_info(资产信息表)


 
 
CREATE DATABASE `test` ;use test;CREATE TABLE `fund_info` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `account` varchar(50) NOT NULL COMMENT '账号',  `amount` decimal(10,2) DEFAULT NULL COMMENT '总金额',  `consume` decimal(10,2) DEFAULT '0.00' COMMENT '消费金额',  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,  `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1DATABASE `test` ;
use test;
CREATE TABLE `fund_info` (
  `id` int(11NOT NULL AUTO_INCREMENT,
  `account` varchar(50NOT NULL COMMENT '账号',
  `amount` decimal(10,2DEFAULT NULL COMMENT '总金额',
  `consume` decimal(10,2DEFAULT '0.00' COMMENT '消费金额',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
ENGINE=InnoDB DEFAULT CHARSET=latin1


具体操作(增删改查)看示例代码吧,在代码中尽可能的都注释了。


 
 
import pymysql# 创建MySQL连接connection = pymysql.connect(host='127.0.0.1',  # MySQL服务器地址                             port=3306,         # 服务端口号                             user='root',       # MySQL用户名                             password='root',   # MySQL密码                             db='test',         # 要操作的数据库名称                             charset='utf8mb4') # 连接编码# 创建cursor, 用于执行sqlcursor = connection.cursor()#  增加两条记录。insert_sql = 'insert into fund_info (account, amount) values ("abc@163.com", 100.00)'insert_sql1 = 'insert into fund_info (account, amount) values ("zxc@163.com", 99.00)'# 执行上面两个sql,cursor.execute(insert_sql)cursor.execute(insert_sql1)# 执行增 删 改时 需要commit,不然不会生效connection.commit()# 查询刚才插入的两条数据cursor.execute('select * from fund_info')# fetchall 查看执行的全部结果,返回一个tupleresult_all = cursor.fetchall()""" 输出:result_all : ((2, 'abc@163.com', Decimal('100.00'), Decimal('0.00'), datetime.datetime(2019, 8, 7, 16, 57, 49), datetime.datetime(2019, 8, 7, 16, 57, 49)), (3, 'zxc@163.com', Decimal('99.00'), Decimal('0.00'), datetime.datetime(2019, 8, 7, 16, 57, 49), datetime.datetime(2019, 8, 7, 16, 57, 49)))"""print('result_all :', result_all)# 通过id查询cursor.execute('select amount from fund_info where account="abc@163.com"')# fetone 仍然返回元组result_amount = cursor.fetchone()print(result_amount) # (Decimal('100.00'),)# 更新 账号:abc@163.com 的amount值为200.00cursor.execute('update fund_info set amount=200.00 where account="abc@163.com"')# 执行增 删 改时 需要commit,不然不会生效connection.commit()print('更新成功.')cursor.execute('delete from fund_info where account="abc@163.com"')# 执行增 删 改时 需要commit,不然不会生效connection.commit()print('删除成功.')# 操作完毕之后,必须要关闭连接cursor.close()connection.close()

# 创建MySQL连接
connection = pymysql.connect(host='127.0.0.1',  # MySQL服务器地址
                             port=3306,         # 服务端口号
                             user='root',       # MySQL用户名
                             password='root',   # MySQL密码
                             db='test',         # 要操作的数据库名称
                             charset='utf8mb4'# 连接编码
# 创建cursor, 用于执行sql
cursor = connection.cursor()

#  增加两条记录。
insert_sql = 'insert into fund_info (account, amount) values ("abc@163.com", 100.00)'
insert_sql1 = 'insert into fund_info (account, amount) values ("zxc@163.com", 99.00)'
# 执行上面两个sql,
cursor.execute(insert_sql)
cursor.execute(insert_sql1)
# 执行增 删 改时 需要commit,不然不会生效
connection.commit()

# 查询刚才插入的两条数据
cursor.execute('select * from fund_info')
# fetchall 查看执行的全部结果,返回一个tuple
result_all = cursor.fetchall()
""" 输出:
result_all : 
((2, 'abc@163.com', Decimal('100.00'), Decimal('0.00'), datetime.datetime(2019, 8, 7, 16, 57, 49), datetime.datetime(2019, 8, 7, 16, 57, 49)), 
(3, 'zxc@163.com', Decimal('99.00'), Decimal('0.00'), datetime.datetime(2019, 8, 7, 16, 57, 49), datetime.datetime(2019, 8, 7, 16, 57, 49)))
"""

print('result_all :', result_all)

# 通过id查询
cursor.execute('select amount from fund_info where account="abc@163.com"')
# fetone 仍然返回元组
result_amount = cursor.fetchone()
print(result_amount) # (Decimal('100.00'),)


# 更新 账号:abc@163.com 的amount值为200.00
cursor.execute('update fund_info set amount=200.00 where account="abc@163.com"')
# 执行增 删 改时 需要commit,不然不会生效
connection.commit()
print('更新成功.')

cursor.execute('delete from fund_info where account="abc@163.com"')
# 执行增 删 改时 需要commit,不然不会生效
connection.commit()
print('删除成功.')

# 操作完毕之后,必须要关闭连接
cursor.close()
connection.close()


以上是用PyMySQL操作MySQL的基本知识。 这里想再啰嗦一下事务。


事务


事务: 事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。


通俗的将: 我执行多个sql如果其中一个失败了,那要将之前修改的数据进行还原。 回滚到执行前的状态。


拿我们上面的sql来举例,对于一个账号 account,资金amount、消费金额consume。 我们购物的时候,消费金额增加的同时,钱包里的金额就要对应的减少。   这个增加和减少就是一个事务,不可能只增加消费金额,而不减少总金额。


今天只说一下PyMySQL对事务的处理(如果在MySQL终端进行事务操作,需要手动开启 -- start transaction; )
直接看下面的例子

当前金额:
 
 
mysql> select amount from fund_info where account = 'zxc@163.com';+--------+| amount |+--------+|  99.00 |+--------+1 row in set (0.00 sec)'zxc@163.com';
+--------+
| amount |
+--------+
|  99.00 |
+--------+
1 row in set (0.00 sec)


执行消费代码
 
 
import pymysqlconnection = pymysql.connect(host='127.0.0.1',  # MySQL服务器地址                             port=3306,         # 服务端口号                             user='root',       # MySQL用户名                             password='root',   # MySQL密码                             db='test',         # 要操作的数据库名称                             charset='utf8mb4') # 连接编码# 创建cursor, 用于执行sqlcursor = connection.cursor()# 代表消费的金额price = 15# 此时账户zxc的总金额为99# 账户zxc@163.com 总金额 - pricesql_1 = f'update fund_info set amount = amount - {price} where account = "zxc@163.com"'# 账户zxc@163.com 消费金额 + pricesql_2 = f'update fund_info set consume = consume + {price} where account = "zxc@163.com"'try:    # 查询余额是否足够    cursor.execute('select amount from fund_info where account = "zxc@163.com"')    result = cursor.fetchone()    print(result[0])    # 如果余额不足 抛出异常.    if not result or result[0] < price:        raise Exception('余额不足...')    cursor.execute(sql_1)    print("========= 其他业务逻辑  执行中....")    cursor.execute(sql_2)except Exception as e:    # 事务回滚    connection.rollback()    print(e)finally:    # 提交sql    connection.commit()    # 关闭连接    cursor.close()    connection.close()15

# 此时账户zxc的总金额为99
# 账户zxc@163.com 总金额 - price
sql_1 = 
f'update fund_info set amount = amount - {price} where account = "zxc@163.com"'
# 账户zxc@163.com 消费金额 + price
sql_2 = 
f'update fund_info set consume = consume + {price} where account = "zxc@163.com"'

try:
    
# 查询余额是否足够
    cursor.execute(
'select amount from fund_info where account = "zxc@163.com"')
    result = cursor.fetchone()
    print(result[
0])
    
# 如果余额不足 抛出异常.
    
if not result or result[0] < price:
        
raise Exception('余额不足...')
    cursor.execute(sql_1)
    print(
"========= 其他业务逻辑  执行中....")
    cursor.execute(sql_2)
except Exception as e:
    
# 事务回滚
    connection.rollback()
    print(e)
finally:
    
# 提交sql
    connection.commit()
    
# 关闭连接
    cursor.close()
    connection.close()


执行完毕,查看剩余金额:
 
 
mysql> select amount from fund_info where account = 'zxc@163.com';+--------+| amount |+--------+|  84.00 |+--------+1 row in set (0.00 sec)'zxc@163.com';
+--------+
| amount |
+--------+
|  84.00 |
+--------+
1 row in set (0.00 sec)


在代码中通过raise 模拟异常。演示一下事务的作用
 
 
import pymysqlconnection = pymysql.connect(host='127.0.0.1',  # MySQL服务器地址                             port=3306,         # 服务端口号                             user='root',       # MySQL用户名                             password='root',   # MySQL密码                             db='test',         # 要操作的数据库名称                             charset='utf8mb4') # 连接编码# 创建cursor, 用于执行sqlcursor = connection.cursor()# 代表消费的金额price = 15# 此时账户zxc的总金额为99# 账户zxc@163.com 总金额 - pricesql_1 = f'update fund_info set amount = amount - {price} where account = "zxc@163.com"'# 账户zxc@163.com 消费金额 + pricesql_2 = f'update fund_info set consume = consume + {price} where account = "zxc@163.com"'try:    # 查询余额是否足够    cursor.execute('select amount from fund_info where account = "zxc@163.com"')    result = cursor.fetchone()    print(result[0])    # 如果余额不足 抛出异常.    if not result or result[0] < price:        raise Exception('余额不足...')    cursor.execute(sql_1)    print("========= 其他业务逻辑  执行中....")    raise Exception('模拟业务逻辑异常......')    cursor.execute(sql_2)except Exception as e:    print('---- 开始事务回滚')    # 事务回滚    connection.rollback()    print(e)finally:    # 提交sql    connection.commit()    # 关闭连接    cursor.close()    connection.close()    print('执行完毕')

connection = pymysql.connect(host='127.0.0.1',  # MySQL服务器地址
                             port=3306,         # 服务端口号
                             user='root',       # MySQL用户名
                             password='root',   # MySQL密码
                             db='test',         # 要操作的数据库名称
                             charset='utf8mb4'# 连接编码
# 创建cursor, 用于执行sql
cursor = connection.cursor()

# 代表消费的金额
price = 15

# 此时账户zxc的总金额为99
# 账户zxc@163.com 总金额 - price
sql_1 = f'update fund_info set amount = amount - {price} where account = "zxc@163.com"'
# 账户zxc@163.com 消费金额 + price
sql_2 = f'update fund_info set consume = consume + {price} where account = "zxc@163.com"'

try:
    # 查询余额是否足够
    cursor.execute('select amount from fund_info where account = "zxc@163.com"')
    result = cursor.fetchone()
    print(result[0])
    # 如果余额不足 抛出异常.
    if not result or result[0] < price:
        raise Exception('余额不足...')
    cursor.execute(sql_1)
    print("========= 其他业务逻辑  执行中....")
    raise Exception('模拟业务逻辑异常......')
    cursor.execute(sql_2)
except Exception as e:
    print('---- 开始事务回滚')
    # 事务回滚
    connection.rollback()
    print(e)
finally:
    # 提交sql
    connection.commit()
    # 关闭连接
    cursor.close()
    connection.close()
    print('执行完毕')


控制条输出

 
 
========= 其他业务逻辑  执行中....---- 开始事务回滚模拟业务逻辑异常......执行完毕
---- 开始事务回滚
模拟业务逻辑异常......
执行完毕


查询mysql

 
 
mysql> select amount from fund_info where account = 'zxc@163.com';+--------+| amount |+--------+|  84.00 |+--------+1 row in set (0.00 sec)'zxc@163.com';
+--------+
| amount |
+--------+
|  84.00 |
+--------+
1 row in set (0.00 sec)


即使执行了sql_1(减少总金额的sql语句),金额并没有被改变。 因为在修改consume(执行sql_2)之前程序出现了异常,程序就进行了事务回滚,即: connection.rollback()。 所以数据被还原到了执行事务之前的样子。


以上,便是今天的分享,希望大家喜欢,觉得内容不错的,欢迎点击「在看」支持,谢谢各位。

往期Python Every Day

[每日一题]19、简单理解Python中的__name__ == '__main__'

[每日一题]18、Python中迭代器、生成器、yield

[每日一题]17、用Python将字符串进行特殊的转换

[每日一题]16、用Python算出100万内的雷劈数

[每日一题]15、用Python输出杨辉三角

[每日一题]14、Python中is和== 的区别

[每日一题]13、任意数组,实现一个特定的排序

[每日一题]12、Python中的多线程

[每日一题]11、用Python打印乘法口诀表

[每日一题]10、一道关于九宫格的面试题

[每日一题]9、Python中文件的读取

[每日一题]8、Python中的深拷贝和浅拷贝

[每日一题]7、Python中的super()函数

 [每日一题]6、Python中的可变参数

[每日一题]5、Python中的lambda表达式

[每日一题]4、Python中的迭代器

[每日一题]3、Python实现删除list中重复元素的几种方式

[每日一题]2、Python中的类的定义和装饰器@classmethod与@staticmethod

[每日一题] 1、Python中的可变对象与不可变对象



640?



感谢您的阅读


640?wx_fmt=gif


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值