文章目录

  • 基于Pymysql的数据库的增删改查模版(3)——更新
  • 环境
  • Mysql更新操作语法
  • 数据库更新:类模版实现
  • 初始化
  • 更新事务基本框架
  • 更新指定记录
  • 完整代码
  • 调用示例


基于Pymysql的数据库的增删改查模版(3)——更新

最近在利用Pymysql进行数据库交互时,为了提高程序的可扩展性,实现了一套基本的数据库查询、插入、更新、删除模版,记录下来供日后使用

ps:考虑到文章的独立阅读性,保持了一些重复的内容

环境

Mysql 5.7.2 理论上对于数据库版本没有特殊要求

pymsql 0.9.3

python >= 3.6 保证格式化字符串的使用

Mysql更新操作语法

UPDATE `tablename` SET field1=value1, field2=value2, ...,fieldN=valueN
WHERE origin_field1 = origin_value1 AND ... AND origin_fieldN = origin_valueN;

其中origin_field = origin_value为筛选条件,用于选择被更新的记录。

数据库更新:类模版实现

初始化

class UpdateDB:
    def __init__(self):
        self.db = pymysql.connect('localhost', 'root', 'password', 'database_name')
        self.cursor = self.db.cursor()

初始化部分涉及到数据库的连接,这一部分比较简单,主要是创建游标对象self.cursor,用于执行SQL语句

更新事务基本框架

def modify_query(self, query):
    try:
        self.cursor.execute(query)
        self.db.commit()
        return True
    except Exception as error:
        self.db.rollback()
        return str(error)

这一部分使用游标对象执行SQL语句,正确执行后commit结果至数据库,出现错误时进行rollback,并返回错误信息,比较简单

更新指定记录

设定为按照给定的顺序进行插入

def update_info(self, tablename, *args, **kwargs):
        """
        :param tablename: 被更新的数据库表名
        :param args: WHERE语句的筛选条件元组
        :param kwargs: 被更新的属性列的字典
        """
        # lambda表达式,为非属性值添加单引号,并对单引号进行转义
        pattern = lambda k: "'" + str(k).replace("'", "\\'") + "'" if len(str(k)) != 0 else 'NULL'
        
        judges = ['`' + arg[0] + '` = ' + pattern(arg[1]) for arg in args]
        items = ['`' + item[0] + '` = ' + pattern(item[1]) for item in kwargs.items()]
        query = f"""UPDATE {'`' + tablename + '`'} SET {','.join(items)} WHERE {' AND '.join(judges)};"""
        print(query)
        result = self.modify_query(query)
        return result

更新的关键有三个部分,分别是:

  • python的lambda表达式,用于对传入字段进行预处理
  • python的函数的可变参数
  • python的格式化字符串,也就是f'xxx' 类型的字符串

下面讲解一下SQL语句生成的部分:

  1. *args 参数实际传入一个元组类型的变量,包含了WHERE子句用于筛选的条件
  • MYSQL的语法支持在数字的两端添加引号,因此,为了保证在SQL语句中字符的正确表示,需要在拼接前人为的加上引号,此处默认添加单引号
  • 注意到以上步骤都是在默认value中不包含',因此才为其添加单引号,因此在处理包含单引号的属性值还需要将其进行转义,表示为转义字符,且由于需要经过python和MYSQL的两次转义,故有 replace("'", "\\'") 进行转义
  • 这两步都由lambda表达式来完成
  • 此处的筛选条件默认为相等判别,*args 中包含多个形如 ('field',value)的元组,表明筛选条件为 WHERE field = value...
  1. **kwargs 参数实际传入一个字典类型的变量,包含了将要插入的属性列及对应的值
{
    'field1':'value1',
    'field2':'value2',
    ...
    'fieldN':'valueN'
}

⚠️对于传来的空值,即相应value字符串长度为0的参数会被修改为 NULL ,从而将相应属性置为空

  1. 通过列表生成式以及lambda表达式共同作用*args生成需要WHERE子句筛选条件,如下所示
["`originfield1`= 'originvalue1'", "`originfield2` = 'originvalue2'",..., "`originfieldN`= 'originvalueN'"]
  1. 通过' AND '.join()即可将其拼接成为如下字符串
"`field1`= 'value1' AND `field2` = 'value2' AND ... AND `fieldN`= 'valueN'"

⚠️此处的AND 两端各有一个空格,以保证正确的连接筛选条件

  1. 通过列表生成式以及lambda表达式共同作用**kwargs生成需要插入的属性值列表,如下所示,注意到
["`field1`= 'value1'", "`field2` = 'value2'",..., "`fieldN`= 'valueN'"]
  1. 通过','.join()即可将其拼接成为如下字符串
"`field1`= 'value1', `field2` = 'value2',..., `fieldN`= 'valueN'"
  1. 生成SQL更新语句
UPDATE `tablename` SET field1=value1, field2=value2, ...,fieldN=valueN
WHERE origin_field1 = origin_value1 AND ... AND origin_fieldN = origin_valueN;

完整代码

import pymysql


class UpdateDB:
    def __init__(self):
        self.db = pymysql.connect('localhost', 'root', 'mk123456', 'ST')
        # self.db = pymysql.connect('localhost', 'root', 'password', 'database_name')
        self.cursor = self.db.cursor()

    # 管理基本框架
    def modify_query(self, query):
        try:
            self.cursor.execute(query)
            self.db.commit()
            return True
        except Exception as error:
            self.db.rollback()
            return str(error)

    def update_info(self, tablename, *args, **kwargs):
        """
        :param tablename: 被更新的数据库表名
        :param args: WHERE语句的筛选条件元组
        :param kwargs: 被更新的属性列的字典
        """
        # lambda表达式,为非属性值添加单引号,并对单引号进行转义
        pattern = lambda k: "'" + str(k).replace("'", "\\'") + "'" if len(str(k)) != 0 else 'NULL'

        judges = ['`' + arg[0] + '` = ' + pattern(arg[1]) for arg in args]
        items = ['`' + item[0] + '` = ' + pattern(item[1]) for item in kwargs.items()]
        query = f"""UPDATE {'`' + tablename + '`'} SET {','.join(items)} WHERE {' AND '.join(judges)};"""
        print(query)
        result = self.modify_query(query)
        return result

调用示例

updatedb = UpdateDB()
result = updatedb.update_info('tablename', ('originfield1', 'originvalue1'),
                              ('originfield2', 'originvalue2'),
                              ...
                              ('originfieldN', 'originvalueN'),
                              field1=value1, field2 = field2, ... , fieldN = valueN)

其中:

  • tablename为待更新记录所在的表名
  • originfield是WHERE子句筛选的属性列名
  • originvalue是WHERE子句筛选的属性列值
  • field是被更新的属性列名
  • value是相应属性列被更新后值