首页 > 数据库 >29. 数据库操作

29. 数据库操作

时间:2025-01-17 20:54:27浏览次数:1  
标签:None name int 数据库 29 bool str 操作

一、SQL与数据库

  数据库 (database)是统一管理的、有组织的、可共享的大量数据的集合。数据库将数据存储在一个或多个表格中,管理这个数据库的软件称为 数据库管理系统(database management system, DBMS)。

  数据库不是针对具体的应用程序,而是立足于数据本身的管理,它将所有数据保存在数据库中,进行科学的组织,并借助于数据库管理系统,通过 SQL 与各种应用程序或应用系统连接,使之能方便地使用数据库中的数据。

  关系型数据库管理系统一般都支持结构化查询语言 (structured query language, SQL),SQL 是数据库的基础,通过它可以实现对关系型数据库进行查询、新增、更新、删除、求和和排序等操作。关系型数据库由数据表 (table)构成,数据表的一行数据称为字段,可以在数据库中添加和删除数据表,在数据表中可以查询、添加和删除字段。

  SQL 语句主要分为以下几类:

  • 数据定义语言(data definition language, DDL)。DDL 是 SQL 中定义数据结构和数据库对象的语言,主要关键字有CREATE、ALTER 和 DROP。
  • 数据操纵语言(data manipulation language, DML)。DML 是 SQL 中操纵数据库中数据的语言,可对数据库中的数据进行插入、删除、更新和选择,主要关键字有 INSERT、UPDATE、DELETE 和 SELECT。
  • 事务控制语言(transaction control language, TCL)。TCL 用于管理 DML 对数据所作的修改,主要关键字有提交 COMMIT 和撤销 ROLLBACK。
    • 对数据库的操作需要用 COMMIT 进行确认,事务一经提交就不能撤销,如果要在提交前撤销对数据库的操作,可以用 ROLLBACK 来 “回滚” 到相应事务开始时的状态。
  • 数据控制语言(data control language, DCL)。DCL 是对数据访问权限进行控制、定义安全级别及创建用户的语言,主要关键字有 GRANT 和 REVOKE。

二、SQLite数据库

  SQLite 数据库是一个常用的开源、跨平台、轻量化本机版数据库,可以作为嵌入式数据库使用。Python 自带的 sqlite3 可以实现对 SQLite 数据库的查询,使用前需要用 import sqlite3 语句导入 sqlite3。

  sqlite3 提供了两个基本的类:数据库连接 Connection 和游标 Cursor。用 sqlite3 的 connect(database:str) 方法打开一个已经存在的 SQLite 数据库或新建一个数据库,并返回 Connection 对象,其中 databaseName是本机上已经存储的数据库文件,或者新建立的数据库文件名称,还可取 ":memory:",表示在内存中创建临时数据库。用 Connection 对象的 cursor() 方法获取 Cursor 对象,用 Cursor 对象提供的方法可以执行 SQL 指令。

  数据库连接 Connection 类的常用方法如下:

cursor() -> Cursor                  # 创建并返回Cursor对象
commit() -> None                    # 提交当前的事务
interrupt() -> None                 # 停止还未执行的任务
rollback() -> None                  # 放弃对数据库的操作,返回到调用commit()时的状态
close() -> None                     # 关闭数据库
backup(target:Connection) -> None   # 将数据备份到另一个数据库中

  游标 Cursor 用于执行 SQL 语句,它的常用方法如下:

execute(sql:sqk, parameters:Sequence=()) -> None    # 执行一条SQL语句,parameters是SQL中的占位符的值
executemany(sql:str, parameters:Sequence) -> None   # 重复执行SQL语句,parameters是SQL中的占位符的值
executescript(sql_script:str) -> None               # 执行多条SQL语句

fetchone() -> Tuple                                 # 获取数据表中的下一行数据构成的元组或None
fetchmany(size:int=cursor.arraysize) -> List        # 获取多行数据,构成的列表,参数size是要获取的行数
fetchall() -> List                                  # 获取所有剩余的行构成的列表

close() -> None                                     # 关闭游标
import sqlite3

connection = sqlite3.connect("test.db")         # 获取连接
cursor = connection.cursor()                    # 获取游标

# 执行SQL语句,创建表
cursor.execute("create table if not exists user(name varchar(20), age int)")

# 向表中插入数据,新增用户信息
cursor.execute("insert into user(name,age) values('Sakura',10)")
cursor.execute("insert into user(name,age) values('Mikoto',14)")
cursor.execute("insert into user(name,age) values('Shana',15)")

# 执行查询结果
cursor.execute("select * from user")
# 获取查询结果
result = cursor.fetchone()                     # 使用fetchone()获取一条记录
print(result,end="\n\n")

result = cursor.fetchmany(2)                   # 使用fetchmany()获取多条记录
print(result,end="\n\n")

result = cursor.fetchall()                     # 使用fetchall()获取全部查询结果
print(result,end="\n\n")

# 修改用户信息
# 使用问号作为占位符代替具体的数值,然后使用一个元组来替代问号
# 使用占位符的方式可以避免SQL注入的风险
cursor.execute("update user set age = ? where name = ?",(12,"Sakura"))
cursor.execute("select * from user where name = ?",("Sakura",))
result = cursor.fetchall()
print(result,end="\n\n")

# 删除用户数据
cursor.execute("delete from user where name = ?",("Shana",))
cursor.execute("select * from user")
result = cursor.fetchall()
print(result,end="\n\n")

cursor.close()                                  # 关闭游标
connection.close()                              # 关闭数据库

三、PySide6对数据库的操作

  PySide6 提供了对常用数据库的驱动,可以从数据库中进行查询、读取、写入、修改、删除数据等操作,同时提供了可视化的控件和数据库数据模型,可以将数据从数据库读取到数据模型中,然后用 Model/View 结构在图形界面中对数据进行操作。

  PySide6 可以驱动常用的关系型数据库,在对数据库进行操作之前需要用 QSqlDatabase 类建立对数据库的连接,然后再用 QSqlQuery 类执行 SQL 命令,实现对数据库的操作。

  我们可以在终端中使用 pip 安装 pyside6 模块。

pip install pyside6

3.1、数据库连接

  在对数据库进行操作之前,需要先建立对数据库的连接。数据库连接用 QSqlDatabase 类。

  用 QSqlDatabase 创建实例的方法如下所示:

QSqlDatabase()
QSqlDatabase(type:str)

  其中 type 是数据库的驱动类型,可取的值下所示。如果要建立自定义的驱动类型,可以创建 QSqlDriver 的子类。

"QDB2"           # IBM DB2数据库
"QIBASE"         # Borlad InterBase数据库
"QMYSQL"         # MySQL数据库
"QODBC"          # 支持ODBC接口的数据库
"QPSQL"          # PostgreSQL数据库
"QSQLITE"        # SQLite数据库
"QOCI"           # Oracle数据库

  QSqlDatabase 类的常用方法如下:

# 实例方法
connectionName() -> str                                                             # 获取连接的名称
driverName() -> str                                                                 # 获取驱动类型的名称

setDatabaseName(name:str) -> None                                                   # 设置连接的数据库名称
databaseName() -> str                                                               # 获取连接的数据库名称
setHostName(host:str) -> None                                                       # 设置连接的主机名称
hostName() -> str                                                                   # 获取连接的主机名称
setPort(port:int) -> None                                                           # 设置连接的端口号
port() -> int                                                                       # 获取连接的端口号
setUserName(username:str) -> None                                                   # 设置用户名
userName() -> str                                                                   # 获取用户名
setPassword(password:str) -> None                                                   # 设置密码
password() -> str                                                                   # 获取密码
setConnectOptions(options="") -> None                                               # 设置连接选项
connectOptions() -> str                                                             # 获取连接参数

open() -> bool                                                                      # 打开数据库
open(user:str, password:str) -> bool                                                # 打开数据库
isOpen() -> bool                                                                    # 获取数据库是否打开
isOpenError() -> bool                                                               # 获取打开数据库是是否出错
isValid() -> bool                                                                   # 获取连接是否有效
close() -> None                                                                     # 关闭连接

transaction() -> bool                                                               # 开启事务
commit() -> bool                                                                    # 提交事务
rollback() -> bool                                                                  # 回滚事务
lastError() -> QSqlError                                                            # 获取最后的错误信息
record(tablename:str) -> QSqlRecord                                                 # 获取含有字段名称的记录

setNumericalPrecisionPolicy(precisionPolicy:QSql.NumericalPrecisionPolicy) -> None  # 设置对数据库进行查询时默认的数值精度
tables(type:QSql.TableType=QSql.Tables) -> List[str]                                # 根据表格类型参数,获取数据库中的表格名称

# 静态方法
drivers() -> List[str]                                                              # 获取系统支持的驱动类型
isDriverAvailable(name:str) -> bool                                                 # 获取是否支持某种类型的驱动

# 添加数据库连接
addDatabase(driver:str, connectionName:str=QLatin1StringView(QSqlDatabase.defaultConnection)) -> QSqlDatabase

# 根据连接名称获取数据库连接
database(connectionName:str=QLatin1StringView(QSqlDatabase.defaultConnection), open:bool=true) -> QSqlDatabase

removeDatabase(connectionName:str) -> None                                          # 删除数据库连接

connectionNames() -> List[str]                                                      # 获取已经添加的连接名称

# 如果connectionNames()返回值中有指定的连接,则返回True
contains(connectionName:str=QLatin1StringView(QSqlDatabase.defaultConnection)) -> bool

  用静态方法 addDatabase(type:str,connectionName:str='qt_sql_default_connection') 添加某种驱动类型的连接,其中参数 type 是驱动类型。对同一个数据库可以添加多个连接,数据库连接的识别是通过连接名称 connectionName 来区分的,而不是关联的数据库。如果不输入连接名称,则该连接作为默认连接,将使用默认的连接名称 'qt_sql_default_connection'

  在用 open() 方法打开数据库前,需要分别用 setDatabaseName(name:str) 方法、setHostName(host:str) 方法、setPassword(password:str) 方法、setPort(port:int) 方法、setUserName(name:str) 方法、setConnectOptions(options:str='') 方法设置连接的数据库文件名、主机名、密码、端口号、用户名和连接参数,如果用 open() 方法打开数据库后再设置这些参数将不起作用。

  在用 setDatabaseName(name:str) 方法打开 SQLite 数据库时,如果数据库不存在则创建新数据库,参数 name 也可取 ':memory:',在内存中临时创建数据库,程序运行结束后删除数据库。对于 ODBC 数据库,参数 nam e是 *.dsn 文件或连接字符串;对于 Oracle 数据库,name 参数是 TNS服务名称

  用 setConnectOptions(options:str='') 方法设置数据库的参数,不同的驱动类型需要设置的参数也不同,各参数值之间用分号 “;” 隔开,例如 SQLite 数据库,可选参数如下:

QSQLITE_BUSY_TIMEOUT
QSQLITE_OPEN_READONLY
QSQLITE_OPEN_URI
QSQLITE_ENABLE_SHARED_CACHE
QSQLITE_ENABLE_REGEXP
QSQLITE_NO_USE_EXTENDED_RESULT_CODES

  用 tables(type:QSql.TableType=QSql.Tables) 方法获取数据库中存在的数据表名称列表,其中 type 取值是 QSql.TableType 的枚举值,可取值如下:

QSql.TableType.Tables           # 对用户可见的所有表
QSql.TableType.SystemTables     # 数据库使用的内部表
QSql.TableType.Views            # 对用户可见的所有视图
QSql.TableType.AllTables        # 以上三种表和视图

  用 setNumericalPrecisionPolicy(precisionPolicy:QSql.NumericalPrecisionPolicy) 方法设置对数据库进行查询时默认的数值精度,参数 precisionPolicy 可取值如下:

QSql.NumericalPrecisionPolicy.LowPrecisionInt32     # 32位整数,忽略小数部分
QSql.NumericalPrecisionPolicy.LowPrecisionInt64     # 64位整数,忽略小数部分
QSql.NumericalPrecisionPolicy.LowPrecisionDouble    # 双精度值,默认值
QSql.NumericalPrecisionPolicy.HighPrecision         # 保持数据的原有精度

  用 lastError() 方法获取最后的出错信息 QSqlError 对象,用 QSqlError 的 type() 方法可以获取出错类型,返回值是 QSqlError.ErrorType 的枚举值或 -1(不能确定错误类型),QSqlError.ErrorType 的枚举值如下:

QSqlError.ErrorType.NoError            # 0,没有错误
QSqlError.ErrorType.ConnectionError    # 1,数据库连接错误
QSqlError.ErrorType.StatementError     # 2,SQL命令语法错误
QSqlError.ErrorType.TransactionError   # 3,事务错误
QSqlError.ErrorType.UnknownError       # 4,未知错误

3.2、数据库查询

  数据库查询 QSqlQuery 用于执行标准的 SQ L命令,例如 CREATE TABLE、SELECT、INSERT、UPDATE、DELETE 等,还可执行特定的非标准的 SQL 命令。

  用 QSqlQuery 类创建实例对象的方法如下所示:

QSqlQuery(db:QSqlDatabase)
QSqlQuery(other:QSqlQuery)
QSqlQuery(query:str="", db:QSqlDatabase=Default(QSqldatabase))

  QSqlQuery 类常用方法如下:

prepare(query:str) -> bool                                                  # 准备SQL语句,成功返回True

addBindValue(val:Any, type:QSql.ParamType=QSql.In) -> None                  # 如果prepare(query)中有占位符,则按顺序依次设置占位符的值
bindValue(placeholder:str, val:Any, type:QSql.ParamType=QSql.In) -> None    # 如果prepare(query)中有占位符,则根据占位名称设置占位符的值
bindValue(pos:int, val:Any, type:QSql.ParamType=QSql.In) -> None            # 如果prepare(query)中有占位符,则根据占位位置设置占位符的值

boundValue(placeholder:str) -> Any                                          # 根据占位符名称获取绑定值
boundValue(pos:int) -> Any                                                  # 根据占位位置获取绑定值
boundValues() -> List[Any]                                                  # 获取绑定值列表

exec() -> bool                                                              # 执行prepare(query)准备的SQL语句
exec(query:str) -> bool                                                     # 执行SQL语句,成功返回True
# 批处理用prepare()方法准备的命令
execBatch(mode:QSqlQuery.BatchExecutionMode=QSqlQuery.BatchExecutionMode.ValuesAsRows) -> bool

finish() -> None                                                            # 完成查询,不再获取数据
clear() -> None                                                             # 清空结果,释放所有资源,查询处于不活跃状态

executedQuery() -> str                                                      # 返回最后正确执行的SQL语句
lastQuery() -> str                                                          # 返回当前查询使用使用的SQL语句

# 返回查询的当前内部位置,第一个记录位置是0,如果位置无效,则返回值是QSql.BeforeFirstRow(值是-1)或QSql.AfterLastRow(值是-2)
at() -> int

isSelect() -> bool                                                          # 当前SQL语句是SELECT语句时返回True
isValid() -> bool                                                           # 当前查询定位在有效记录时返回True
isActive() -> bool                                                          # 获取查询是否处于活跃状态
isNull(field:int) -> bool                                                   # 将查询处于非活跃状态,查询定位在无效记录或空字段上时返回True
isNull(name:str) -> bool                                                    # 将查询处于非活跃状态,查询定位在无效记录或空字段上时返回True

first() -> bool                                                             # 将当前查询位置定位在第一个记录
last() -> bool                                                              # 将当前查询位置定位到最后一个记录
previous() -> bool                                                          # 将当前查询位置定位到前一个记录
next() -> bool                                                              # 将当前查询位置定位到下一个记录
seek(i:int, relative:bool=false) -> bool                                    # 将当前查询位置定位到指定记录

setForwardOnly(forward:bool) -> None                                        # 当forward取True时,只能用next()和seek()方法来定位结果,此时,seek()参数为正值
isForwardOnly() -> bool                                                     # 获取定位模式

lastError() -> QSqlError                                                    # 返回最近出错信息
lastInsertId() -> Any                                                       # 返回最近插入行的对象ID号
nextResult() -> bool                                                        # 放弃当前查询结果并定位到下一个结果
record() -> QSqlRecord                                                      # 返回查询指向的当前记录

size() -> int                                                               # 返回查询结果的记录数,无法确定、非SELECT命令或数据库不支持该功能是返回-1、
value(i:int) -> Any                                                         # 根据字段索引,获取当前记录的字段值
value(name:int) -> Any                                                      # 根据字段名称,获取当前记录的字段值

numRowsAffected() -> int                                                    # 获取受影响的行的个数,无法确定或查询处于非活跃状态时返回-1
swap(other:QSqlQuery) -> None                                               # 与其它查询交换数据

  用 exec(query:str) 方法直接执行 SQL 命令。也可以用 prepare(query:str)方法准备要执行的 SQL 命令;用 exec()方法或 execBatch(mode=QSqlQuery.ValuesAsRows) 方法执行已经准备好的 SQL 命令,其中 mode 可取值如下:

QSqlQuery.BatchExecutionMode.ValuesAsRows    # 更新多行,列表中的每个值作为一个值来更新下一行
QSqlQuery.BatchExecutionMode.ValuesAsColumns # 更新一行,列表作为一个值来使用

  在用 prepare(query:str) 方法准备 SQL 命令时,SQL 命令中可以有占位符,占位符可以用问号 "?"(ODBC 格式),也可以用冒号 ":surname"(Oracle 格式)。占位符的真实值可以用 addBindValue(val:Any,type:QSql.ParamType=QSql.In) 方法按照 顺序 依次设置,也可用 bindValue(placeholder:str,val:Any,type:QSql.ParamType=QSql.In) 方法根据 占位符的名称 设置,还可以用 bindValue(pos:int,val:Any,type:QSql.ParamType=QSql.In) 方法根据 占位符的位置 设置,其中参数 type可取值如下:

QSql.ParamTypeFlag.In        # 绑定参数输入到数据库中
QSql.ParamTypeFlag.Out       # 绑定参数从数据库中接收数据
QSql.ParamTypeFlag.InOut     # 既可以将数据输入到数据库中,也可以从数据库中接收数据
QSql.ParamTypeFlag.Binary    # 数据是二进制,需要将“|”与以上三种参数联合使用

  当返回的结果有多个记录时,需要首先定位到所需要的记录上,当 isActive() 方法和 isSelect() 方法的返回值是 True 时,可以用 first()last()previous()next() 方法分别定位到 第一个记录最后一个记录前一个记录下一个记录 上,成功则返回 True;用 seek(index:int,relative:bool=False) 方法可以 定位到指定的记录 上。如果只是想从开始到结束浏览数据,可以设置 setForwardOnly(True),这样可以节省大量的内存。

  用 value(index:int) 方法或 value(name:str) 方法获取当前记录的字段值。也可用 record() 方法获取当前的记录对象 QSqlRecord,QSqlRecord 是指数据表(table)或视图(view)中的一行,然后用记录对象的 value(index:int) 方法或 value(name:str) 方法获取字段的值,用记录对象的 count() 方法获取字段的数量,用 indexOf(name:str) 方法获取字段的索引。

from PySide6.QtSql import QSqlDatabase, QSqlQuery

if __name__ == "__main__":
    person = (("Sakura", 10), ("Mikoto", 14), ("Shana", 15))

    # 1.添加数据库连接
    db = QSqlDatabase.addDatabase("QSQLITE")

    # 2.设置连接数据库的名称
    db_name = "./test.db"
    db.setDatabaseName(db_name)

    # 3.创建数据库查询对象
    query = QSqlQuery(db)

    # 3.打开数据库
    if db.open():
        # 4.执行SQL语句,创建表
        query.exec("create table if not exists user(name varchar(20), age int)")

        # 6.开启事务
        if db.transaction():
            for i in person:
                # 7.准备SQL语句
                query.prepare("insert into user(name, age) values(?, ?)")
                # 7.1.按顺序设置占位符的值
                query.addBindValue(i[0])
                # 7.2.按索引位置设置占位符的值
                query.bindValue(1, i[1])

                # 8.执行SQL语句
                query.exec()

            # 9.提交事务
            db.commit()

        # 10.查询数据
        if query.exec("select * from user"):
            while query.next():
                print(query.value("name"), query.value("age"))

        # 11.关闭数据库
        db.close()

四、数据库Model/View结构

  PySide6 提供了对数据库进行可视化操作的 Model/View 结构,通过数据库模型读入在数据库中查询到的数据,并通过视图控件(如 QTableView)显示数据库模型中的数据,通过代理控件在视图控件中对数据进行新增、更新、删除等操作,再通过数据模型把操作后的数据保存到数据库中。PySide6 提供的数据库模型有 QSqlQueryModel、QSqlTableModel 和 QSqlRelationalTableModel。

数据模型继承关系

4.1、数据库查询模型

  数据库查询模型 QSqlQueryModel 只能从数据库中读取数据,而不能修改数据,可以用视图控件

  用 QSqlQueryModel 创建数据库查询模型对象的方法如下所示。

QSqlQueryModel(paarent:QObject=None)

  QSqlQueryModel 类常用方法如下:

setQuery(query:QSqlQuery) -> None                               # 设置数据库查询
setQuery(query:str, db:QSqkDatabase=QSqlDatabase()) -> None     # 设置数据库查询
query() -> QSqlQuery                                            # 获取数据库查询
record() -> QSqlRecord                                          # 获取包含字段信息的空记录
record(row:int) -> QSqlRecord                                   # 获取指定行的记录
clear() -> None                                                 # 清空查询模型中的数据

# 设置显示数据的视图控件表头某角色的值
setHeaderData(section:int, orientation:Qt.Orientation, value:Any, role:int=Qt.EditRole) -> bool
# 获取显示数据的视图控件表头某种角色的值
headerData(section:int, orientation:Qt.Orientation, role:int=Qt.DisplayRole) -> Any

rowCount(parent:QModelIndex=QModelIndex()) -> int               # 获取数据表中记录(行的数量)
columnCount(parent:QModelIndex=QModelIndex()) -> int            # 获取数据表中列的数量

  用 setQuery(query:QSqlQuery) 方法或 setQuery(query:str,db:QSqlDatabase=Default(QSqlDatabase)) 方法设置数据库查询 QSqlQuery;用 setHeaderData(section:int,orientation:Qt.Orientation,value:Any,role:int=Qt.EditRole) 方法设置显示数据的视图控件表头某角色的值,在 orientation 取 Qt.Horizontal,并且 section 取值合适时返回 True,其他情况返回 False,其中 value 是某种角色的值,section 是列索引。

import sys

from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QTableView
from PySide6.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
from PySide6.QtCore import Qt

class MyWidget(QWidget):
    def __init__(self):
        # 1.调用父类Qwidget类的__init__()方法
        super().__init__()
        # 2.使用数据库
        self.useDataBase()
        # 3.调用setupUi()方法初始化页面
        self.setup_ui()

    def setup_ui(self):
        # 1.设置窗口对象大小
        self.resize(700, 500)
        # 2.设置表格控件
        self.tableView = QTableView(self)
        self.tableView.resize(700, 500)
        # 3.设置表格控件的模型
        self.tableView.setModel(self.sqlQueryModel)

    def useDataBase(self):
        person = (("Sakura", 10), ("Mikoto", 14), ("Shana", 15))

        # 1.添加数据库连接
        db = QSqlDatabase.addDatabase("QSQLITE")

        # 2.设置连接数据库的名称
        db_name = "./test.db"
        db.setDatabaseName(db_name)

        # 3.创建数据库查询对象
        query = QSqlQuery(db)

        # 4.创建数据库查询模型
        self.sqlQueryModel = QSqlQueryModel()

        # 5.打开数据库
        if db.open():
            # 6.执行SQL语句,创建表
            self.sqlQueryModel.setQuery("create table if not exists user(name varchar(20), age int)")

            # 7.开启事务
            if db.transaction():
                for i in person:
                    # 8.准备SQL语句
                    query.prepare("insert into user(name, age) values(?, ?)")
                    # 8.1.按顺序设置占位符的值
                    query.addBindValue(i[0])
                    # 8.2.按索引位置设置占位符的值
                    query.bindValue(1, i[1])

                    # 9.执行SQL语句
                    query.exec()

                # 10.提交事务
                db.commit()

        # 11.设置查询
        self.sqlQueryModel.setQuery("select * from user")

        # 12.获取字段信息当作头部信息
        header = self.sqlQueryModel.record()
        for i in range(header.count()):
            # 13.设置显示数据的视图控件表头某角色的值
            self.sqlQueryModel.setHeaderData(i, Qt.Orientation.Horizontal, header.fieldName(i), Qt.ItemDataRole.DisplayRole)

        # 14.关闭数据库
        db.close()

if __name__ == "__main__":
    # 1.创建一个QApplication类的实例
    app = QApplication(sys.argv)
    # 2.创建一个窗口
    window = MyWidget()
    # 3.展示窗口
    window.show()
    # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
    sys.exit(app.exec())

4.2、数据库表格模型

  数据库表格模型 QSqlTableModel 借助视图控件可以对查询到的数据进行修改、插入、删除和排序等操作,同时将修改后的数据更新到数据库中。

  用 QSqlTableModel 创建数据库表格模型的方法如下所示:

QSqlTableModel(parent:QObject=None, db:QSqlDatabase=Default(QSqlDataBase))

  数据库表格模型 QSqlTableModel 的常用犯法按如下所示:

# 实例方法
insertRows(row:int, count:int, parent:QModelIndex=QModelIndex()) -> bool        # 插入多个空行,在OnFieldChange和OnRowChange模式下每次只能插入一行
removeRow(row:int, parent:QModelIndex=QModelIndex()) -> bool                    # 删除指定行
removeRows(row:int, count:int, parent:QModelIndex=QModelIndex()) -> bool        # 删除多行
insertColumns(column:int, count:int, parent:QModelIndex=QModelIndex()) -> bool  # 插入多个空列
removeColumn(column:int, parent:QModelIndex=QModelIndex()) -> bool              # 删除指定列
removeColumns(column:int, count:int, parent:QModelIndex=QModelIndex()) -> bool  # 删除多列
revert() -> None                                                                # 恢复数据模型到初始状态  
submit() -> bool                                                                # 提交数据模型中的所有更改
rowCount(parent:QModelIndex=QModelIndex()) -> int                               # 获取行的数量
columnCount(parent:QModelIndex=QModelIndex()) -> int                            # 获取列的数量
setData(index:QModelIndex, value:Any, role:Qt.ItemDataRole=Qt.EditRole) -> bool # 设置指定索引的数据项的角色值
data(index:QModelIndex, role:Qt.ItemDataRole=Qt.EditRole) -> Any                # 获取指定索引的数据项的角色值
sort(column:int, order:Qt.SortOrder=Qt.AscendingOrder) -> None                  # 直接对结果进行排序
index(row:int, column:int, parent:QModelIndex=QModelIndex()) -> QModelIndex     # 获取子索引
parent(child:QModelIndex)-> QModelIndex                                         # 获取子索引的父索引
sibling(row:int, column:int, idx:QModelIndex) -> QModelIndex                    # 获取指定索引的兄弟索引
clearItemData(index:QModelIndex) -> bool                                        # 根据索引清除数据项中的数据

setEditStrategy(strategy:QSqlTableModel.EditStrategy) -> None                   # 设置修改提交模式
database() -> QSqlDatabase                                                      # 获取关联的数据库连接
deleteRowFromTable(row:int) -> bool                                             # 直接删除数据表中指定的行(记录)
fieldIndex(fieldName:str) -> int                                                # 获取字段的索引,-1表示没有对应的字段
insertRecord(row:int, record:QSqlRecord) -> bool                                # 在指定行位置插入行
insertRowIntoTable(values:QSqlDatabase) -> bool                                 # 直接在数据表中插入行

isDirty() -> bool                                                               # 获取模型中是否有脏数据
isDirty(index:QModelIndex) -> bool                                              # 根据索引获取数据数据是否时脏数据
primaryValues(row:int) -> QSqlRecord                                            # 返回指定行的含有表格字段的记录
revertRow(row:int) -> None                                                      # 复原指定行的更改

setRecord(row:int, record:QSqlRecord) -> bool                                   # 用指定的记录填充指定的行
setTable(tableName:str) -> None                                                 # 设置数据表中的字段名称
setFilter(filter:str) -> None                                                   # 设置SELECT查询语句中WHERE子句部分 
filter() -> str                                                                 # 获取SELECT查询语句中WHERE子句部分
setSort(column:int, order:Qt.SortOrder) -> None                                 # 设置SELECT查询语句中ORDER BY子句部分
orderByClause() -> str                                                          # 获取SELECT查询语句中ORDER BY子句部分

select() -> bool                                                                # 执行SELECT查询语句
selectRow(row:int) -> bool                                                      # 用数据库库中行更新模型中的数据
selectStatement() -> bool                                                       # 获取"SELECT ... WHERE ... ORDER BY..."

# 槽函数
revertAll() -> None                                                             # 复原所有未提交的更改
submitAll() -> bool                                                             # 提交所有更改

  数据库表格模型 QSqlTableModel 的常用犯法按如下所示:

beforeDelete(row:int)                       # 在调用deleteRowFromTable(row:int)方法删除指定行之前发色和信号
beforeInsert(record:QSqlRecord)             # 在调用insertRowIntoTable(values:QSqlRecord)方法插入记录之前发射信号,可以在插入之前修改记录
beforeUpdate(row:int, record:QSqlRecord)    # 在调用updateRowInTable(row:int, values:QSqlRecord)方法更新指定行之前发射信号
primeInsert(row:int, record:QSqlRecord)     # 在调用insertRows(row:int, column:int)方法对新插入的行进行初始化时发射信号

  记录 QSqlRecord 表示数据表中的一行数据,一行数据中每个字段有不同的值,可用 QSqlTableModel 的 record(row:int) 方法获取 QSqlRecord 对象,以获取数据表中的一行数据。

  用 QSqlRecord 创建记录实例对象的方法如下所示。

QSqlRecord()
QSqlRecord(other:QSqlRecord)

  QSqlRecord 常用的方法如下所示。

append(field:QSqlField) -> None                     # 在末尾添加字段
insert(pos:int, field:QSqlField) -> None            # 在自会顶的位置插入字段
remove(pos:int) -> None                             # 删除指定位置的字段
replace(pos:int, field:QSqlField) -> None           # 替换指定位置的字段
setValue(name:str, val:Any) -> None                 # 根据字段名称设置字段的值
setValue(i:int, val:Any) -> None                    # 根据字段索引设置字段的值
value(name:str) -> Any                              # 根据字段名称获取字段的值
value(i:int) -> Any                                 # 根据字段索引获取字段的值
setNull(name:str) -> None                           # 根据字段名称设置字段为NULL
setNull(i:int) -> None                              # 根据字段索引设置字段为NULL
isNull(name:str) -> bool                            # 根据字段名称判断字段是否为NULL
isNull(i:int) -> bool                               # 根据字段索引判断字段是否为NULL
clear() -> None                                     # 删除所有的字段
isEmpty() -> bool                                   # 获取是否含有字段
clearValues() -> None                               # 删除所有的字段值
contains(name:str) -> bool                          # 获取是否包含指定的字段
count() -> int                                      # 获取字段的数量
field(name:str) -> QSqlField                        # 根据字段名称获取字段
field(i:int) -> QSqlField                           # 根据字段索引获取字段
fieldName(i:int) -> str                             # 获取字段的名称
indexOf(name:str) -> int                            # 获取字段的索引
keyValues(keyFields:QSqlRecord) -> QSqlRecord       # 获取与给定的记录具有相同字段名称的记录
setGenerated(name:str, generated:bool) -> None      # 根据索引设置字段值是否已经生成
setGenerated(i:int, generated:bool) -> None         # 根据索引设置字段值是否已经生成
isGenerated(name:str) -> bool                       # 根据索引获取字段是否已经生成
isGenerated(i:int) -> bool                          # 根据名称获取字段是否已经生成

  用 append(field:QSqlField) 方法可以在末尾添加字段;用 insert(pos:int,field:QSqlField) 方法插入字段;用 remove(pos:int) 方法移除字段;用 setValue(i:int,val:Any) 方法或 setValue(name:str,val:Any) 方法根据字段索引或字段名称设置字段的值;用 setGenerated(i:int,generated:bool) 方法或 setGenerated(name:str,generated:bool) 方法根据索引或名称设置字段值是否已经生成,只有已经生成的字段值才能用 QSqlTableModel 的 updateRowInTable(row:int,values:QSqlRecord) 方法更新到数据库中,默认值是 True。

  字段 QSqlField 是数据表中的列,一个记录由多个字段构成。字段的属性有字段名、字段类型和字段值等。用 QSqlRecord 的 field(i:int) 方法或 field(name:str) 方法可获得 QSqlField。

  用 QSqlField 创建字段的方法如下所示。

QSqlField(fieldName:str="", type:QMetaType:Default(QMetaType), tableName:str="")
QSqlField(other:QSqlField)

  其中 type 用于定义字段的类型,可取 PySide 中常见的类。

  QSqlField 类的常用方法如下:

setName(name:str) -> None                                       # 设置字段的名称
name() -> str                                                   # 获取字段的名称
setValue(value:Any) -> None                                     # 获取字段的值,只读时不能设置值
value() -> Any                                                  # 获取字段的值,只读时不能设置值
setDefaultValue(value:Any) -> None                              # 设置字段的默认值
defaultValue() -> Any                                           # 获取字段的默认值
setMetaType(type:QMetaType) -> None                             # 设置字段的类型
metaType() -> QMetaType                                         # 获取存储在数据库中的类型
setReadOnly(readOnly:bool) -> None                              # 设置是否只读,只读时不能修改字段的值
isReadOnly() -> bool                                            # 获取是否只读
setRequired(required:bool) -> None                              # 设置字段的值是必须要输入还是可见的
setRequiredStatus(status:QSqlFieldRequiredStatus) -> None       # 设置可选状态
setGenerated(gen:bool) -> None                                  # 设置字段的生成状态
isGenerated() -> bool                                           # 获取字段的生成状态
setLength(fieldLength:int) -> None                              # 设置字段的长度
length() -> int                                                 # 获取字段的长度
setPrecision(precision:int) -> None                             # 设置浮点数的精度
precision() -> int                                              # 获取浮点数的精度
setTableName(tableName:str) -> None                             # 设置数据表名称
tableName() -> str                                              # 获取数据表名称
setAutoValue(autoVal:bool) -> None                              # 将字段的值标记是由数据库自动生成的
isAutoValue() -> bool                                           # 获取字段的值是否是由数据库自动生成的
isValid() -> bool                                               # 获取字段的类型是否有效
clear() -> None                                                 # 清除字段的值并设置成None
isNull() -> bool                                                # 获取字段的值是否为None

  用 setName(name:str) 方法设置字段名称;用 setValue(value:Any) 方法设置字段的值;用 setDefaultValue(value:Any) 方法设置字段的默认值;用 setReadOnly(readOnly:bool) 方法设置是否是只读,在只读状态不能更改字段的值。用 setRequired(required:bool) 方法或 setRequiredStatus(status:QSqlField.RequiredStatus) 方法设置字段的值是必须要输入的还是可选的,其中参数 status 可取值如下:

QSqlField.RequiredStatus.Required
QSqlField.RequiredStatus.Optional
QSqlField.RequiredStatus.Unknown
import sys

from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QTableView
from PySide6.QtSql import QSqlDatabase, QSqlTableModel, QSqlRecord

class MyWidget(QWidget):
    def __init__(self):
        # 1.调用父类Qwidget类的__init__()方法
        super().__init__()
        # 2.使用数据库
        self.useDataBase()
        # 3.调用setupUi()方法初始化页面
        self.setup_ui()

    def setup_ui(self):
        # 1.设置窗口对象大小
        self.resize(700, 500)
        # 2.设置表格控件
        self.tableView = QTableView(self)
        self.tableView.resize(700, 500)
        # 3.设置表格控件的模型
        self.tableView.setModel(self.sqlTableModel)

    def useDataBase(self):
        persons = [{"name": "Sakura", "age": 10}, {"name": "Mikoto", "age": 14}, {"name": "Shana", "age": 10}]

        # 1.添加数据库连接
        db = QSqlDatabase.addDatabase("QSQLITE")

        # 2.设置连接数据库的名称
        db_name = "./test.db"
        db.setDatabaseName(db_name)

        # 3.创建数据库表格模型
        self.sqlTableModel = QSqlTableModel(self, db)

        # 4.打开数据库
        if db.open():
            # 5.执行SQL语句,创建表
            self.sqlTableModel.setQuery("create table if not exists user(name varchar(20), age int)")

            # 6.设置数据表中字段的名称
            self.sqlTableModel.setTable("user")

            # 7.开启事务
            if db.transaction():
                for i, person in enumerate(persons):
                    # 8.创建QSqlRecord对象,表示数据表中的一行数据
                    record = QSqlRecord(self.sqlTableModel.record())
                    for key, value in person.items():
                        # 9.根据字段名称设置字段的值
                        record.setValue(key, value)
                    # 10.在指定位置插入行
                    self.sqlTableModel.insertRecord(i, record)
                # 11.提交事务
                db.commit()

        # 12.查询数据
        self.sqlTableModel.select()

        # 13.关闭数据库
        db.close()

if __name__ == "__main__":
    # 1.创建一个QApplication类的实例
    app = QApplication(sys.argv)
    # 2.创建一个窗口
    window = MyWidget()
    # 3.展示窗口
    window.show()
    # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
    sys.exit(app.exec())

4.3、关系表格模型

  数据库关系表格模型 QSqlRelationalTableModel 继承自 QSqlTableModel,除具有 QSqlTableModel 的方法外,它还提供了外键功能。关系表格模型 QSqlRelationalTableModel 实现了 SQL 的 SELECT 命令中的 INNER JOIN 和 LEFT JOIN 功能。

  用 QSqlRelationalTableModel 类创建关系表格模型的方法如下所示。

QSqlRelationalTableModel(parent:QObject=None, db:QSqlDatabase=Default(QSqlDatabase))

  用 QSqlRelationalTableModel 的 setRelation(column:int,relation:QSqlRelation) 方法定义 QSqlRelationalTableModel 当前数据表格(如 table1)的外键和映射关系,其中参数 column 是 table1 的字段编号,用于确定 table1 中当作外键的字段 field1,relation 参数是 QSqlRelation 的实例对象,用于确定另外一个数据表格(如 table2)和对应的字段 field2。

  QSqlRelation 实例对象的创建方法是 QSqlRelation(tableName:str,indexCol:str,displayCol:str),其中 tableName 用于确定第 2 个数据表格 table2,indexCol 用于指定 table2 的字段 field2,displayCol 是 table2 中用于显示在 table1 的 field1 位置处的字段 field3,用 field3 的值显示在 field1 位置处,field1 的值不显示。

  另外用 QSqlRelationalTableModel 的 setJoinMode(joinMode:QSqlRelationalTableModel.JoinMode) 方法可设置两个数据表格的数据映射模式,即使 table1 和 table2 没有匹配的数据,也列出 table1 中的数据。参数 joinMode 可取值如下:

QSqlRelationalTableModel.InnerJoin    # 内连接,值为0,只列出table1和table2中匹配的数据
QSqlRelationalTableModel.LeftJoin     # 左连接,值为1

标签:None,name,int,数据库,29,bool,str,操作
From: https://www.cnblogs.com/FlurryHeart/p/18677645

相关文章

  • 【Python】Selenium根据网页页面长度,模拟向下滚动鼠标,直到网页底部的操作
    最近在弄selenium的爬取的过程中,我发现一些网站上的表格,是需要手动拉到底部才能加载完成的。如果没有拉到底部,那么在获取网页表格的时候,表格就会只有显示的一部分,页面就不完整。所以我就整理了一些模拟滚动鼠标,加载到页面底部的方法。用于处理这个问题~以下是几种常见的......
  • 深入理解第三范式(3NF):数据库设计中的重要性与实践
    title:深入理解第三范式(3NF):数据库设计中的重要性与实践date:2025/1/17updated:2025/1/17author:cmdragonexcerpt:在数据库设计中,规范化是确保数据完整性、减少冗余和提高查询效率的关键过程。第三范式(3NF)作为关系数据库设计的高级规范,建立在前两范式(1NF和2NF)的......
  • 深入理解第二范式(2NF):提升数据库设计的有效性与灵活性
    title:深入理解第二范式(2NF):提升数据库设计的有效性与灵活性date:2025/1/16updated:2025/1/16author:cmdragonexcerpt:数据库的规范化是确保数据完整性和消除数据冗余的关键过程。第二范式(2NF)是关系数据库设计中的重要概念,进一步建立在第一范式的基础之上。通过......
  • 数据库系统
    数据库系统的发展演进结构化、半结构化、非结构化数据的区别结构化数据半结构化数据非结构化数据结构性严格固定具有一定结构,非严格无固定结构存储方式关系型数据库文档数据库、文件存储文件系统、大数据存储查询难度简单(SQL)中等(NoSQL/查询工具)......
  • Laminin Pentapeptide YIGSR-NH2;层粘连蛋白五肽;抗黏附肽;YIGSR;LAMININ (929-933)肽;1105
    YIGSR 简介    YIGSR是一种能够抑制白血病细胞肿瘤生长和转移的多肽。YIGSR通过67kDa层粘连蛋白结合蛋白阻断细胞与层粘连蛋白I的结合,并抑制剪切诱导的层粘连蛋白细胞 eNOS 表达增加。   【中文名称】层粘连蛋白(929-933);抗黏附肽;酪氨酰-异亮氨酰-......
  • SpringBoot实验课程管理系统8t062(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表学生,实验老师,班级,实验室,实验室预约,课程类型,课程信息,课表信息开题报告内容一、选题背景与意义随着信息技术的快速发展和教育改革的深入,实验课程管理在教......
  • SpringBoot实训实习职业技能管理系统9621h(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表学员,教师,工作类型,招聘信息,投简信息,视频类型,实训教学,实训技能,课程名称,教师评价,部门信息,实习,学员打卡开题报告内容一、项目背景与目的随着社会的发展......
  • Linux操作命令之文件服务
    一、vsftpd服务vsftpd服务:c/sb/s 浏览器/服务器模式        软件包:                服务端:vsftpd-3.0.2-25.el7.x86_64.rpm                客户端:lftp-4.4.8-11.el7.x86_64.rpm        端口:        ......
  • JSP美发信息综合服务与管理系统5hxk2(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、研究背景与意义随着人们生活水平的提高,越来越多的人开始注重个人形象和美容美发。传统的手工管理方式已经无法满足现代美发店的需求,因此,开发美......
  • JSP芒果分销系统s94qu--程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、题目芒果分销系统的设计与实现二、研究背景及意义随着信息技术的飞速发展,农业与信息技术的融合已成为推动农业现代化进程的关键力量。果农及......