事务操作流程(重点)

\1. 创建连接

\2. 获取游标

\3. 执行sql

\1. 查询操作(select)

\2. 非查询操作(insert/update/delete)

\1. 事务提交(连接对象.commit())2. 事务回滚(连接对象.rollback())

\4. 关闭游标

\5. 关闭连接

游标及使用

我们可以将“ 游标 ”简单的看成是结果集的一个指针,可以根据需要在结果集上面来回滚动,

浏览我需要的数据。

``

import pymysql

conn = pymysql.connect(host="localhost",
                       port=3306,
                       user="root",
                       password="123456",
                       database="books")

cursor = conn.cursor()

sql = "select id, title, `read`, `comment` from t_book"
cursor.execute(sql)

# cursor.rowcount获取查询结果的总记录数
print("获取的查询结果记录行数为:", cursor.rowcount)

# cursor.fetchone()获取查询结果的第一条数据
print("查询结果的第一条数据为:", cursor.fetchone())

# cursor.fetchall()获取全部的查询结果
# 先重置游标位置
cursor.rownumber = 0
print("全部的查询结果为:", cursor.fetchall())

cursor.close()
conn.close()

查询与非查询(插入、更新、删除)操作小结:

相同点(可封装复用去冗余):基本操作流程是一样

创建连接--获取游标--执行sql--关闭游标--关闭连接

不同点

要执行sql语句不一样

非查询操作需要手动开启事务(在创建连接时,指定参数autocommit=True)

数据库事务操作

案例——事务操作的必要性

1).连接到数据库(host:localhost user:root password:root database:books),

并开启自动提交事务

2).新增一条图书数据(id:4 title:西游记 pub_date:1986-01-01 )

3).故意抛出一个异常(模拟代码出现异常)

4).新增一条英雄人物数据(name:孙悟空 gender:1 book_id:4)

image-20220530202822301

解决方法

用函数实现

1.导包

try:

程序前期,需要执行的代码2.创建连接对象

3.获取游标对象

4.执行sql

\+ 在图书表中插入一行数据

\+ 主动抛出异常

\+ 在英雄人物表中插入一行数据

调用提交事务:conn.commit()

except:

程序出现异常后,处理代码

调用事务回滚:conn.rollback()

finally:

程序结束时,需要执行的代码

5.关闭游标

6.关闭连接

数据库工具封装

# 导包
import pymysql

# 创建工具类
class DBUtil():
    # 初始化
    __conn = None
    __cursor = None

    # 创建连接
    @classmethod
    def __get_conn(cls):
        if cls.__conn is None:
            cls.__conn = pymysql.connect(host="localhost",
                                         port=3306,
                                         user="root",
                                         password="root",
                                         database="books")
        return cls.__conn

    # 获取游标
    @classmethod
    def __get_cursor(cls):
        if cls.__cursor is None:
            cls.__cursor = cls.__get_conn().cursor()
        return cls.__cursor

    # 执行sql
    @classmethod
    def exe_sql(cls, sql):
        try:
            # 获取游标对象
            cursor = cls.__get_cursor()
            # 调用游标对象的execute方法,执行sql
            cursor.execute(sql)
            #  如果是查询
            if sql.split()[0].lower() == "select":
                # 返回所有数据
                return cursor.fetchall()
            #  否则:
            else:
                # 提交事务
                cls.__conn.commit()
                # 返回受影响的行数
                return cursor.rowcount
        except Exception as e:
            # 事务回滚
            cls.__conn.rollback()
            # 打印异常信息
            print(e)
        finally:
            # 关闭游标
            cls.__close_cursor()
            # 关闭连接
            cls.__close_conn()

    # 关闭游标
    @classmethod
    def __close_cursor(cls):
        if cls.__cursor:
            cls.__cursor.close()
            cls.__cursor = None

    # 关闭连接
    @classmethod
    def __close_conn(cls):
        if cls.__conn:
            cls.__conn.close()
            cls.__conn = None