22|SQLite文本数据库:如何进行数据管理(下)?
在上节提到了使用比较简单的 SQL 来操作 SQLite,并讲解了数据库的基本操作步骤。
不过当你的程序功能越来越强大的时候,随之而来的就是代码的复杂度越来越高。像是上一讲,我们在进行 SQLite 数据库搜索的时候,你需要建立连接、申请游标对象,才能进行查询。而这些准备工作,我们更希望在程序运行的时候就准备好,这样就不必多次重复编写。
而且对数据库进行增删改查能够通过尽可能少的 SQL 来实现数据库的操作。那么能实现这一功能的就是类。
通过类,你可以为越来越复杂的程序编写结构更清晰的代码。同时也能更好地把 SQLite 的增删改查封装成一个独立的对象,便于你调用数据库时能进行数据持久化。
那么今天这节,就使用类来实现 SQLite 数据的读取和写入。与此同时,会继续以通讯录为例,来给你讲解,如果使用了比较复杂的 SQL 来操作 SQLite 时,怎么合理组织代码结构,让你更优雅地书写代码。
使用类实现 SQLite 的读写
由于类这个概念比较抽象,还是采用老办法帮你理解它,将使用“类”对 SQLite 的读写 SQL 操作进行封装,并将类进行实例化以后进行调用,得到 SQLite 中的通讯录数据。先把代码贴出来,供你参考:
import sqlite3
import pathlibclass OptSqlite(object):def __init__(self, dbname = "new.db"):""":param dbname 数据库名称"""self.dir = pathlib.PurePath(__file__).parentself.db = pathlib.PurePath(self.dir, dbname)self.conn = sqlite3.connect(self.db)self.cur = self.conn.cursor()def close(self):"""关闭连接"""self.cur.close()self.conn.close()def get_one_phone(self, username):"""获取一个联系人的电话"""self.get_user_phone_sql = f"""SELECT phone FROM address_book WHERE name = "{username}" """try:self.result = self.cur.execute(self.get_user_phone_sql)return self.result.fetchone()except Exception as e:print(f"失败原因是:{e}")def set_one_phone(self, name, phone):"""增加一个联系人"""self.set_user_phone_sql = '''INSERT INTO address_bookVALUES (?, ?, ?)'''self.v = (2, str(name), int(phone))try:self.cur.execute(self.set_user_phone_sql, self.v)self.conn.commit()except Exception as e:print(f"失败原因是:{e}")if __name__ == "__main__":my_query = OptSqlite("contents.db")my_query.set_one_phone("Jerry","12344445555")phone = my_query.get_one_phone("Tom")phone2 = my_query.get_one_phone("Jerry") my_query.close()print(phone)print(phone2)# 输出结果
# (12377778888,)
# (12344445555,)
在这段代码中,我使用类实现了两个连续操作:添加新的联系人“Jerry”,并取出联系人“Tom”和“Jerry”的手机号码。
通过代码,你会发现类的实现思路和语法,跟函数有非常大的区别,因此在你第一次使用类代替函数实现通讯录时,我要通过实现方式和语法方面来为你做个详细的对比,并且为你讲解类的初始化函数,在类实例化时是如何实现接收参数并自动初始化的。
总体来说,与使用函数实现数据库操作相比,类的最大优势就是完善的封装。
在使用类实现“SELECT”和“INSERT”这两个 SQL 操作的时候,你只需进行了一次初始化和关闭连接,后续的 SQL 操作都可以复用这次的连接,类能有效减少重复建立连接和重复初始化的工作。
因此在类似数据库封装这种功能复杂的代码中,你会看到更多的人选择用类代替自定