SQLite3 使用Python快速操作单体文件的sqlite数据库

PY-SQLite3

Note: XLY23333
RAW Video: check
Python Version: 3.11

SQLite3 使用Python快速操作单体文件的sqlite数据库_第1张图片
SQL基础操作可参考文章:
[CSDN] SQL Basic VERSION1
[CSDN] SQL Basic VERSION2

DataBase基础概念

关系型数据库常见操作

即SQL(Structured Query Language)语法

  • 创建/删除/修改 表 CREATE/DROP/ALTER TABLE
  • 新增/删除/更新 记录 INSERT/DELETE/UPDATE INFO
  • 查询内容 SELECT
  • 创建/删除 索引 CREATE/DROP INDEX

SQLite3基础

开源、嵌入式关系型数据库引擎,其数据库就是一个db文件,直接存放在本地

Python3内嵌SQLite,无需再安装,只需要通过sqlite3模块驱动

SQLite数据库的数据类型

SQLite使用一个更普遍的动态类型系统。在SQLite中,值得数据类型与值本身是相关的,而不是与它的容器相关

SaveType Description
NULL 空值
INTEGER 带符号的整数,根据值大小存储(6种不同长度类型)
REAL 浮点值,存储为8字节的IEEE浮点数
TEXT 文本字符串,使用数据库编码(UTF-8/UTF-16BE/UTF-16LE)
BLOB 二进制数据,完全根据输入存储

⚠️:SQLite3同样支持SQL标准数据类型(如varchar), 但更推荐使用更普遍的动态类型系统

递增主键

COde: INTEGER PRIMARY KEY AUTOINCREMENT
后续INSERT时可以省略id传入,但是需要使用指定行的方法INSER

INSERT INTO <TableName> (
    <Col1, Col2, ...>
)VALUES(
    (?, ?, ...)    
)

插入新类别之后,可通过category_id = c.lastrowid 获取新插入的类别ID

主键级联操作

写在外键后面的内容,用于确定级联操作

Format:

CREATE TABLE <TableName>(
    <ColName1> <DataType> <Addition>,
    <ColName2> <DataType> <Addition>,
    <ColName3> <DataType> <Addition>,
    ...
    <ColNameN> <DataType> <Addition>,
    FOREIGN KEY (<ColName>) REFERENCES <OtherTableName> (<ColName>) 
        ON DELETE/UPDATE <ADDITION>
)

ADDITION:

  • CASCADE: 级联删除/更新时,同时删除/更新引用该外键的记录
  • SET NULL: 级联删除/更新时,将引用该外键的记录设置为NULL
  • SET DEFAULT: 级联删除/更新时,将引用该外键的记录设置为默认值
  • RESTRICT: 级联操作被禁止(Default)
  • NO ACTION: 级联操作被禁止(同RESTRICT)

最常用的操作:

FOREIGN KEY (<ColName>) 
    REFERENCES <OtherTableName> (<ColName>)
    ON DELETE CASCADE  -- 级联删除
    ON UPDATE SET NULL  -- 级联更新

⚠️:外键约束的启用需要在每个数据库连接后立即执行,而不是仅在创建数据库时
即需要在每次连接数据库时执行PRAGMA foreign_keys = ON;
Py操作时则需要在连接数据库后执行conn.execute('PRAGMA foreign_keys = ON')
级联操作会导致数据完整性问题,请慎用!

Python操作SQLite3数据库

Python数据库应用DB-API接口

标准化连接对象方法

  • .close() 关闭DB连接
  • .commit() 将未完成的事务提交到数据库
  • .rollback() 将数据库回滚到未完成事务的开始状态
  • .cursor() 在数据库连接上创建一个cursor对象

游标cursor

一段私有的SQL工作区,即内存区域,用于暂时存放受SQL语句影响到的数据,可以理解为受影响的数据放置在一个虚表中,虚表即为游标

cursor执行SQL
Method Description
execute(operation[, parameters]) 在数据库上执行SQL操作语法(operation: SQL语句字符串),parameters是语句字符串中变量值的序列或映射
executemany(operation[, paramseq]) 执行多条SQL命令,将每条命令所需的变量值存储在parameq序列中
cursor获取查询结果集
Method Description
fetchone() 返回查询数据库后得到下一行的结果集(List/Tuple)
fetchmany([size]) 返回查询结果行的序列,可选参数size代表行数
fetchall() 返回全部剩余的查询结果行的序列
nextset() 跳到下一结果集,准备获取其信息
cursor对象属性
Property Description
arraysize 为fetchmany()方法提供的默认整数值,表示一次返回结果集行数
description 返回当前集的列名信息
rowcount 返回查询结果的行数-1表示没有结果集

Python连接SQLite数据库应用一般流程

创建DB和TABLES

以存储书为例,DB包括两个表:category(记录分类)和book(记录书籍信息)
一本书归属于某个分类因此book有一个外键(foreign key),指向category表的主键id

category
book
id /int/
sort /int/
name /text/
id /int/
sort /int/
name /text/
price /real/
category /int/

Python Code:

import os
import sqlite3  # SQLite3模块

def CreateTable():
    # 创建连接数据库
    DB_PATH = os.path.join(os.path.dirname(os.getcwd()), 'DB', 'demoDB.db')
    # print(DB_PATH)
    conn = sqlite3.connect(DB_PATH)
    # 创建游标
    c = conn.cursor()
    # CREATE TABLE
    '''
    设置id为递增INTEGER主键
    Book表的category外键连接到category表的id列
    '''
    table1_sql = '''
    CREATE TABLE category(
        id INTEGER PRIMARY KEY AUTOINCREMENT, 
        sort INTEGER,
        name TEXT
    )
    '''
    c.execute(table1_sql)
    table2_sql = '''
    CREATE TABLE book(
        id INTEGER PRIMARY KEY AUTOINCREMENT, 
        sort INTEGER, 
        name TEXT, 
        price REAL, 
        category INTEGER,
        FOREIGN KEY (category) REFERENCES category(id) 
            ON DELETE CASCADE
            ON UPDATE CASCADE
    )
    '''
    c.execute(table2_sql)
    # 提交事务 save the changes
    conn.commit()
    # 在已经建成的表当中插入新列
    c.execute('ALTER TABLE category ADD COLUMN score TEXT NULL')
    conn.commit()
    # 关闭连接
    conn.close()
    print("[INFO] Success CREATE DB")
插入数据

Python Code:

def InsertData():
    # 创建连接数据库
    DB_PATH = os.path.join(os.path.dirname(os.getcwd()), 'DB', 'demoDB.db')
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    # 准备数据
    '''
    由于使用了递增INTEGER主键, 可以不导入id, 但是INSERT不可省略列信息
    '''
    bookls = [
        (1, 'Python入门', 88.8, 1),
        (3, 'Java入门', 99.9, 2),
        (2, 'C++入门', 120.0, 1),
        (4, 'C#入门', 150.0, 2),
        (5, 'Ruby入门', 180.0, 1),
        (8, 'PHP入门', 200.0, 2),
        (7, 'JavaScript入门', 220.0, 1),
        (6, 'Swift入门', 250.0, 2),
        (9, 'Kotlin入门', 280.0, 1),
        (10, 'Go入门', 300.0, 2),
    ]
    # SQL语句提交数据
    ## 单句SQL执行
    c.execute('INSERT INTO category (sort, name) VALUES (1, "Normal")')
    ## 使用?占位导入list/Tuple数据
    c.execute('INSERT INTO category (sort, name) VALUES (?, ?)',
                  [2, "WEB"])    
    ## 多句SQL执行
    c.executemany('INSERT INTO book (sort, name, price, category) VALUES (?, ?, ?, ?)',
                  bookls)
    conn.commit()
    conn.close()
    print("[INFO] Success INSERT INFO")
查询数据

Python Code:

def SelectData():
    DB_PATH = os.path.join(os.path.dirname(os.getcwd()), 'DB', 'demoDB.db')
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    # 按sort排序查询sort第一的书名
    c.execute('SELECT name FROM book ORDER BY sort')
    print('===SORT SELECT ONE===\n', 
          c.fetchone())
    # 查询所有category=2的所有book信息
    c.execute('SELECT * FROM book WHERE category=1')
    print('===WHERE SELECT ALL===\n', 
          c.fetchall())
    # 迭代用法
    print('===iter SELECT===')
    for row in c.execute('SELECT name, price FROM book ORDER BY sort'):
        print(row)
    ## 使用JOIN方法查询对应外键
    foreign_sql = '''
    SELECT book.name, category.name, book.price 
    FROM book 
    JOIN category ON book.category = category.id
    ORDER BY book.price DESC
    '''
    c.execute(foreign_sql)
    print('===FOREIGN JOIN ON SELECT===\n', 
          c.fetchall())
    conn.close()

SQL Code:

-- 选择书名、分类名、书价列
SELECT book.name, category.name, book.price
-- 从book表中
FROM book
-- JOIN合并book、category表
JOIN category 
-- 合并条件:两者属性相等
ON book.category = category.id
-- 条件: book的category属性=2
WHERE book.category=2
-- 排序:倒序按书本价格排序
ORDER BY book.price DESC;

Tips:

  • 查询所有表: c.execute('SELECT * FROM sqlite_master WHERE type="table"')
  • 查询表结构: c.execute('PRAGMA table_info(tableName)')
删除数据

Python Code:

def _showdata(DB_path, sql_cmd:str = None):
    conn = sqlite3.connect(DB_path)
    c = conn.cursor()
    c.execute(sql_cmd)
    info = c.fetchall()
    conn.close()
    print(info)
    return info

def DeleteData():
    DB_PATH = os.path.join(os.path.dirname(os.getcwd()), 'DB', 'demoDB.db')
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()
    conn.execute('PRAGMA foreign_keys = ON')  # 启用外键约束
    # 新增新类别food
    c.execute('INSERT INTO category (sort, name) VALUES (?, ?)', (3, 'food'))
    category_id = c.lastrowid  # 获取新插入的类别ID
    print(f'Last Row ID: {category_id}')
    # 新增书food1~5
    foodls = [
        (1, '西红柿炒鸡蛋', 10.0, category_id),
        (2, '香菇炒鸡蛋', 15.0, category_id),
        (3, '豆腐煎蛋', 20.0, category_id)
    ]
    c.executemany('INSERT INTO book (sort, name, price, category) VALUES (?, ?, ?, ?)',
                  foodls)
    conn.commit()
    print('===INSERT DATA===')
    _showdata(DB_PATH, 'SELECT * FROM category')
    _showdata(DB_PATH,  ''' SELECT book.name, book.price, category.name 
                            FROM book 
                            JOIN category 
                                ON book.category=category.id
                            ORDER BY book.price DESC
                        ''')
    # 删除新类别food
    c.execute('DELETE FROM category WHERE name="food"')
    conn.commit()
    print('===DELETE DATA===')
    _showdata(DB_PATH, 'SELECT * FROM category')
    _showdata(DB_PATH,  ''' SELECT book.name, book.price, category.name 
                            FROM book 
                            JOIN category 
                                ON book.category=category.id
                            ORDER BY book.price DESC
                        ''')
    conn.close()

你可能感兴趣的:(SQL,Python,数据库,sqlite,python)