Flask之七:sqlite3数据库(原生SQL)

基本思路

  • 写一个数据库操作的实例db,这个实例绑定具体的sqlite数据库,并且可以对这个数据库执行SQL语句
  • 各级蓝图都导入这个实例,通过这个实例直接用SQL语句操作数据库
  • 但是:由于现在ORM比较方便,而且ORM也可以通过SQL语句来直接操作数据库,所以这个实例的意义不大

注意:各级文件的路径是从哪里开始算起的

数据库操作实例db

# dbconn.py
# --------------------------------
"""
    使用说明:

    使用时只需要指定sqlite3数据库的路径, 然后把这个文件中的db导入, 然户就可以使用db来操作它绑定的数据库了

    Sqlite3数据库管理员db,负责执行各种SQL语句;
    用法:导入db, db.exe()、db.exep(,)、db.sql()
    返回: (成功与否T/F,查询到的行数,附加信息,查询结果数据集=含元组的list)

    1. Sqlite3Admin类是操作sqlite3数据库的类
    2. 方法==exe==用于:执行insert|delete|update语句
        接受参数灵活:
            1. 一条sql语句的str
            2. 一组sql语句str组成的list
        返回:(成功与否T/F,受影响的行数,附加信息)
    3. 方法==exep==用于执行带参数的sql语句,主要是insert
        接受参数
            1-sql语句模版,如: insert into user values (null, ?, ?)
            2-参数的列表,如 (('Jim', 27), ('Tim', 56), ('Janny', 21)),也很灵活, list和tuple混用也行, 但是建议全部用list:
                [[], []]、([], [])、((), ())、[(), ()]、[[], ()]
        返回:(成功与否T/F,受影响的行数,附加信息)
    4. 方法==sql==用于执行select语句,返回查询结果
        接受参数:
            sql_str_list: SQL语句,str/list,如果是list则只取其中第一个字符串
            返回: (成功与否T/F,查询到的行数,附加信息,查询结果数据集=含元组的list)
    """


# 我自己的py模块, 主要是用SQL语句原生操作数据库的, 不依赖其他的模块
import sqlite3


# 唯一需要设计的内容: sqlite3数据库路径
sqlite3_database_file_path_from_root = 'sqlite3/my.db'  # 文件路径要从主py执行起算,因为这些模块最终都是导入到主py文件里去执行的,都是以主py文件所在的地方(root根目录)作为查找文件的起点


class Sqlite3Basic(object):
    """
    Sqlite3数据库连接的基础类,负责数据库连接、断开;用于后续子类的扩展
    """
    sqlite3_name = sqlite3_database_file_path_from_root  # 数据库路径及文件名
    obj_conn = None  # 数据库连接对象
    obj_cursor = None  # 游标对象

    # 连接数据库,并创建游标
    @classmethod
    def conn(cls):
        cls.obj_conn = sqlite3.connect(cls.sqlite3_name)  # 创建数据库链接
        cls.obj_cursor = cls.obj_conn.cursor()  # 创建游标

    # 关闭游标,并断开数据库
    @classmethod
    def disconn(cls):
        cls.obj_cursor.close()  # 关闭游标
        cls.obj_conn.commit()  # 提交事务
        cls.obj_conn.close()  # 关闭数据库链接


class Sqlite3Admin(Sqlite3Basic):
    # 执行sql语句进行insert delete update操作,返回受影响的行数
    @classmethod
    def exe(cls, sql_str_list):
        """
        执行一条/多条 insert|update|delete 语句(exe=执行)

        千万注意!insert时不要忘记对字符串加''!
        :param sql_str_list: SQL语句,可以是str(一句)也可以是list[str](多句)
        :return: (成功与否T/F,受影响的行数,附加信息)
        """
        # 1. 连接数据库
        cls.conn()
        # 2. 执行操作语句
        rowcount = 0  # 记录受影响的条数
        # 如果sql语句是一个list,那就一条一条的执行
        if isinstance(sql_str_list, list):  # 推荐用isinstance代替type这里
            for sql_i in sql_str_list:
                cls.obj_cursor.execute(sql_i)
                rowcount += cls.obj_cursor.rowcount
        # 不然就只有一句sql语句
        else:
            cls.obj_cursor.execute(sql_str_list)
            rowcount = cls.obj_cursor.rowcount
        # 3. 关闭数据库
        cls.disconn()
        # 4. 设限返回值
        if rowcount == -1:  # -1表示发生错误
            return False, rowcount, '错误:未知错误!请检查!'
        elif rowcount == 0:
            return False, rowcount, '错误:受影响的数据条数=[0],请检查!'
        else:
            return True, rowcount, '成功'

    # 同时执行多条sql语句 executemany
    @classmethod
    def exep(cls, sql_model: str, para_list_tuple):
        """
        执行多条sql(一般是insert)语句,效率更高,exep=执行带参数(para)

        千万注意!insert时不要忘记对字符串加''!
        :param sql_model: sql模版语句,如 'insert into user values (null, ? ?)'
        :param para_list_tuple: ?参数的list,本身及成员可以是list或者tuple,最后都要转为tuple
        :return: (成功与否T/F,受影响的行数,附加信息)
        """
        # 1. 连接数据库
        cls.conn()
        # 2. 执行操作语句
        # 如果成员是list,则转为tuple
        para_list_tuple = [tuple(p) for p in para_list_tuple if isinstance(p, list)]
        # 如果参数本身是list,则转为tuple
        para_list_tuple = tuple(para_list_tuple) if not isinstance(para_list_tuple, tuple) else para_list_tuple
        # 执行executemany()方法
        cls.obj_cursor.executemany(sql_model, para_list_tuple)
        rowcount = cls.obj_cursor.rowcount  # 记录受影响的条数
        # 3. 关闭数据库
        cls.disconn()
        # 4. 设限返回值
        if rowcount == -1:  # -1表示发生错误
            return False, rowcount, '错误:未知错误!请检查!'
        elif rowcount == 0:
            return False, rowcount, '受影:响的数据条数=[0],请检查!'
        else:
            return True, rowcount, '成功'

    # 查询语句,返回数据集
    @classmethod
    def sql(cls, sql_str_list):
        """
        执行 select 语句

        :param sql_str_list: SQL语句,str/list,如果是list则只取其中第一个字符串
        :return: (成功与否T/F,查询到的行数,附加信息,查询结果数据集=含元组的list)
        """
        # 1. 连接数据库
        cls.conn()
        # 2. 执行查询语句
        # 兼容一下:如果参数的一个list,则取其第一个作为sql查询语句
        sql_str_list = sql_str_list[0] if isinstance(sql_str_list, list) else sql_str_list
        # 执行
        cls.obj_cursor.execute(sql_str_list)
        rs = cls.obj_cursor.fetchall()  # 这是一个list,里面是tuple: [(), ()]
        rowcount = len(rs)
        # 3. 关闭数据库
        cls.disconn()
        # 4. 返回值
        if rowcount == -1:  # -1表示发生错误
            return False, rowcount, '错误:未知错误!请检查!', []
        else:
            return True, rowcount, '成功,查询结果[%d]条' % rowcount, rs


# 数据库实例,直接使用db的方法就可以了!其他py文件直接导入去用
db = Sqlite3Admin()


# 测试
if __name__ == '__main__':
    # 关于不停的left join、left join的用法
    # 写作:TABLE1 left   outer        join TABLE2 on    TABLE1.A = TABLE2.C
    # 读作: 表1   在左边 不匹配也不删行 关联   表2  条件是      这个==这个
    sql = ('select e.id, e.name, e.age, b.name, ea.address from employee as e '
           'left outer join bumen as b on e.bumen_id = b.id '
           'left outer join employee_address as ea on e.id = ea.employee_id')
    print(db.sql(sql))

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351