Python SQLite3数据库操作类分享


Posted in Python onJune 10, 2014

接触Python时间也不是很长的,最近有个项目需要分析数据,于是选用Python为编程语言,除了语言特性外主要还是看重Python对于SQLite3数据库良好的支持能力了,因为需要灵活处理大量的中间数据。

刚开始一些模块我还乐此不疲的写SQL语句,后来渐渐厌倦了,回想到以前捣鼓C#的时候利用反射初步构建了个SQL查询构造器,直到发现linq,于是放弃了这个计划,当然微软后来又推出了Entity Framework,这些都是后话了,而且现在我对微软的东西兴趣不是很大的,好了,扯多了,下面继续正文。

对了,再扯一句,优秀的博客程序Drupal也使用了类似的查询构造器进行数据库查询,避免直接写SQL语句,另外这样做的一点点好处就是,可以一定程度的屏蔽平台相关性,对于数据库迁移还是有帮助的。

不过我今天介绍的数据库辅助类查询构造器是个很简单的东东,甚至只限于SQLite数据库,如果有童鞋感兴趣可以完善下,我目前只要操作SQLite顺手就可以了,对于比较大的数据库应用就直接上ORM吧。

先看代码:

import sqlite3# ***************************************************
# *
# * Description: Python操作SQLite3数据库辅助类(查询构造器)
# * Author: wangye
# *
# ***************************************************
def _wrap_value(value):
    return repr(value)
def _wrap_values(values):
    return list(map(_wrap_value, values))
def _wrap_fields(fields):
    for key,value in fields.items():
        fields[key] = _wrap_value(value)
    return fields
def _concat_keys(keys):
    return "[" + "],[".join(keys) + "]"
def _concat_values(values):
    return ",".join(values)
def _concat_fields(fields, operator = (None, ",")):
    if operator:
        unit_operator, group_operator = operator
    # fields = _wrap_fields(fields)
    compiled = []
    for key,value in fields.items():
        compiled.append("[" + key + "]")
        if unit_operator:
            compiled.append(unit_operator)
            compiled.append(value)
        compiled.append(group_operator)
    compiled.pop() # pop last group_operator
    return " ".join(compiled)
class DataCondition(object):
    """
        本类用于操作SQL构造器辅助类的条件语句部分
        例如:
        DataCondition(("=", "AND"), id = 26)
        DataCondition(("=", "AND"), True, id = 26)
    """
    def __init__(self, operator = ("=", "AND"), ingroup = True, **kwargs):
        """
            构造方法
            参数:
                operator 操作符,分为(表达式操作符, 条件运算符)
                ingroup  是否分组,如果分组,将以括号包含
                kwargs   键值元组,包含数据库表的列名以及值
                         注意这里的等于号不等于实际生成SQL语句符号
                         实际符号是由operator[0]控制的
            例如:
            DataCondition(("=", "AND"), id = 26)
            (id=26)
            DataCondition((">", "OR"), id = 26, age = 35)
            (id>26 OR age>35)
            DataCondition(("LIKE", "OR"), False, name = "John", company = "Google")
            name LIKE 'John' OR company LIKE "Google"
        """
        self.ingroup = ingroup
        self.fields = kwargs
        self.operator = operator
    def __unicode__(self):
        self.fields = _wrap_fields(self.fields)
        result = _concat_fields(self.fields, self.operator)
        if self.ingroup:
            return "(" + result + ")"
        return result
    def __str__(self):
        return self.__unicode__()
    def toString(self):
        return self.__unicode__()
class DataHelper(object):
    """
        SQLite3 数据查询辅助类
    """
    def __init__(self, filename):
        """
            构造方法
            参数: filename 为SQLite3 数据库文件名
        """
        self.file_name = filename
    def open(self):
        """
            打开数据库并设置游标
        """
        self.connection = sqlite3.connect(self.file_name)
        self.cursor = self.connection.cursor()
        return self
    def close(self):
        """
            关闭数据库,注意若不显式调用此方法,
            在类被回收时也会尝试调用
        """
        if hasattr(self, "connection") and self.connection:
            self.connection.close()
    def __del__(self):
        """
            析构方法,做一些清理工作
        """
        self.close()
    def commit(self):
        """
            提交事务
            SELECT语句不需要此操作,默认的execute方法的
            commit_at_once设为True会隐式调用此方法,
            否则就需要显示调用本方法。
        """
        self.connection.commit()
    def execute(self, sql = None, commit_at_once = True):
        """
            执行SQL语句
            参数:
                sql  要执行的SQL语句,若为None,则调用构造器生成的SQL语句。
                commit_at_once 是否立即提交事务,如果不立即提交,
                对于非查询操作,则需要调用commit显式提交。
        """
        if not sql:
            sql = self.sql
        self.cursor.execute(sql)
        if commit_at_once:
            self.commit()
    def fetchone(self, sql = None):
        """
            取一条记录
        """
        self.execute(sql, False)
        return self.cursor.fetchone()
    def fetchall(self, sql = None):
        """
            取所有记录
        """
        self.execute(sql, False)
        return self.cursor.fetchall()
    def __concat_keys(self, keys):
        return _concat_keys(keys)
    def __concat_values(self, values):
        return _concat_values(values)
    def table(self, *args):
        """
            设置查询的表,多个表名用逗号分隔
        """
        self.tables = args
        self.tables_snippet = self.__concat_keys(self.tables)
        return self
    def __wrap_value(self, value):
        return _wrap_value(value)
    def __wrap_values(self, values):
        return _wrap_values(values)
    def __wrap_fields(self, fields):
        return _wrap_fields(fields)
    def __where(self):
        # self.condition_snippet
        if hasattr(self, "condition_snippet"):
            self.where_snippet = " WHERE " + self.condition_snippet
    def __select(self):
        template = "SELECT %(keys)s FROM %(tables)s"
        body_snippet_fields = {
            "tables" : self.tables_snippet,
            "keys" : self.__concat_keys(self.body_keys), 
        }
        self.sql = template % body_snippet_fields
    def __insert(self):
        template = "INSERT INTO %(tables)s (%(keys)s) VALUES (%(values)s)"
        body_snippet_fields = {
            "tables" : self.tables_snippet,
            "keys" : self.__concat_keys(list(self.body_fields.keys())),
            "values" : self.__concat_values(list(self.body_fields.values()))
        }
        self.sql = template % body_snippet_fields
    def __update(self):
        template = "UPDATE %(tables)s SET %(fields)s"
        body_snippet_fields = {
            "tables" : self.tables_snippet,
            "fields" : _concat_fields(self.body_fields, ("=",","))
        }
        self.sql = template % body_snippet_fields
    def __delete(self):
        template = "DELETE FROM %(tables)s"
        body_snippet_fields = {
            "tables" : self.tables_snippet
        }
        self.sql = template % body_snippet_fields
    def __build(self):
        {
            "SELECT": self.__select,
            "INSERT": self.__insert,
            "UPDATE": self.__update,
            "DELETE": self.__delete
        }[self.current_token]()
    def __unicode__(self):
        return self.sql
    def __str__(self):
        return self.__unicode__()
    def select(self, *args):
        self.current_token = "SELECT"
        self.body_keys = args
        self.__build()
        return self
    def insert(self, **kwargs):
        self.current_token = "INSERT"
        self.body_fields = self.__wrap_fields(kwargs)
        self.__build()
        return self
    def update(self, **kwargs):
        self.current_token = "UPDATE"
        self.body_fields = self.__wrap_fields(kwargs)
        self.__build()
        return self
    def delete(self, *conditions):
        self.current_token = "DELETE"
        self.__build()
        #if *conditions:
        self.where(*conditions)
        return self
    def where(self, *conditions):
        conditions = list(map(str, conditions))
        self.condition_snippet = " AND ".join(conditions)
        self.__where()
        if hasattr(self, "where_snippet"):
            self.sql += self.where_snippet
        return self

下面举几个例子供大家参考吧:

db = DataHelper("/home/wangye/sample.db3")
db.open() # 打开数据库
db.execute("""
    CREATE TABLE [staffs] (
      [staff_id] INTEGER PRIMARY KEY AUTOINCREMENT,
      [staff_name] TEXT NOT NULL,
      [staff_cardnum] TEXT NOT NULL,
      [staff_reserved] INTEGER NOT NULL
)
""") # 直接执行SQL语句,注意这里commit_at_once默认为Truedb.table("staffs").insert(staff_name="John", staff_cardnum="1001", staff_reserved=0)
# 插入一条记录
rs = db.table("staffs").select("staff_id", "staff_name").fetchall()
# 直接取出所有staff_id和staff_name
rs = db.table("staffs").select("staff_name").where(DataCondition(("=", "AND"), id = 1)).fetchone()
# 取一条staff_id为1的staff_name
rs = db.table("staffs").select("staff_name").where(DataCondition(("<", "AND"), id = 100), DataCondition(("=", "AND"), staff_reserved = 1)).fetchone()
# 取一条id小于100并且staff_reserved为1的staff_name记录
db.close() # 关闭数据库

目前还没有让其支持星号(*)操作符,另外在多表同名列操作方面处理得也不是很好,这个只用于日常简单的脚本操作,最好不要用于生产环境,因为可能有未知问题。

Python 相关文章推荐
Python IDE PyCharm的基本快捷键和配置简介
Nov 04 Python
python3+PyQt5使用数据库窗口视图
Apr 24 Python
Python实现迭代时使用索引的方法示例
Jun 05 Python
Python3常用内置方法代码实例
Nov 18 Python
python 求定积分和不定积分示例
Nov 20 Python
Python安装依赖(包)模块方法详解
Feb 14 Python
matlab、python中矩阵的互相导入导出方式
Jun 01 Python
如何利用python发送邮件
Sep 26 Python
python 读取、写入txt文件的示例
Sep 27 Python
PyCharm Community安装与配置的详细教程
Nov 24 Python
Pandas对每个分组应用apply函数的实现
Dec 13 Python
Python opencv缺陷检测的实现及问题解决
Apr 24 Python
Python不规范的日期字符串处理类
Jun 10 #Python
Python ORM框架SQLAlchemy学习笔记之数据查询实例
Jun 10 #Python
Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
Jun 10 #Python
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
Jun 10 #Python
Python ORM框架SQLAlchemy学习笔记之关系映射实例
Jun 10 #Python
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
Jun 10 #Python
Python使用htpasswd实现基本认证授权的例子
Jun 10 #Python
You might like
php socket方式提交的post详解
2008/07/19 PHP
php实现的简单日志写入函数
2015/03/31 PHP
Yii框架连接mongodb数据库的代码
2016/07/27 PHP
浅析Laravel5中队列的配置及使用
2016/08/04 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
php在windows环境下获得cpu内存实时使用率(推荐)
2018/02/08 PHP
jQuery调用WebService的实现代码
2011/06/19 Javascript
javascript拖拽上传类库DropzoneJS使用方法
2013/12/05 Javascript
javascript和jquery修改a标签的href属性
2013/12/16 Javascript
当某个文本框成为焦点时即清除文本框内容
2014/04/28 Javascript
由ReactJS的Hello world说开来
2015/07/02 Javascript
jQuery获取浏览器类型和版本号的方法
2016/07/05 Javascript
Easyui的组合框的取值与赋值
2016/10/28 Javascript
javascript-解决mongoose数据查询的异步操作
2016/12/22 Javascript
搭建vue开发环境
2018/07/19 Javascript
uni-app实现点赞评论功能
2019/11/25 Javascript
vue中的双向数据绑定原理与常见操作技巧详解
2020/03/16 Javascript
Vue切换div显示隐藏,多选,单选代码解析
2020/07/14 Javascript
Openlayers显示地理位置坐标的方法
2020/09/28 Javascript
Python中的对象,方法,类,实例,函数用法分析
2015/01/15 Python
Python彩色化Linux的命令行终端界面的代码实例分享
2016/07/02 Python
Python实现压缩与解压gzip大文件的方法
2016/09/18 Python
Django 忘记管理员或忘记管理员密码 重设登录密码的方法
2018/05/30 Python
Python秒算24点实现及原理详解
2019/07/29 Python
python使用正则表达式(Regular Expression)方法超详细
2019/12/30 Python
python图片指定区域替换img.paste函数的使用
2020/04/09 Python
python 决策树算法的实现
2020/10/09 Python
安装Anaconda3及使用Jupyter的方法
2020/10/27 Python
基于HTML5+tracking.js实现刷脸支付功能
2020/04/16 HTML / CSS
面向对象编程的优势是什么
2015/12/17 面试题
2014年元旦促销活动方案
2014/02/22 职场文书
英语课外活动总结
2014/08/27 职场文书
学习党的群众路线教育实践活动心得体会范文
2014/11/03 职场文书
2016年寒假社会实践活动总结
2015/03/27 职场文书
《青山不老》教学反思
2016/02/22 职场文书
Nginx+Windows搭建域名访问环境的操作方法
2022/03/17 Servers