29. 数据库操作

news/2025/1/17 20:52:32/文章来源:https://www.cnblogs.com/FlurryHeart/p/18677645

一、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 sqlite3connection = 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) -> QSqlDatabaseremoveDatabase(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语句,成功返回TrueaddBindValue(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) -> boolfinish() -> None                                                            # 完成查询,不再获取数据
clear() -> None                                                             # 清空结果,释放所有资源,查询处于不活跃状态executedQuery() -> str                                                      # 返回最后正确执行的SQL语句
lastQuery() -> str                                                          # 返回当前查询使用使用的SQL语句# 返回查询的当前内部位置,第一个记录位置是0,如果位置无效,则返回值是QSql.BeforeFirstRow(值是-1)或QSql.AfterLastRow(值是-2)
at() -> intisSelect() -> bool                                                          # 当前SQL语句是SELECT语句时返回True
isValid() -> bool                                                           # 当前查询定位在有效记录时返回True
isActive() -> bool                                                          # 获取查询是否处于活跃状态
isNull(field:int) -> bool                                                   # 将查询处于非活跃状态,查询定位在无效记录或空字段上时返回True
isNull(name:str) -> bool                                                    # 将查询处于非活跃状态,查询定位在无效记录或空字段上时返回Truefirst() -> 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, QSqlQueryif __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) -> AnyrowCount(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 sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QTableView
from PySide6.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
from PySide6.QtCore import Qtclass 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 sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtWidgets import QTableView
from PySide6.QtSql import QSqlDatabase, QSqlTableModel, QSqlRecordclass 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/870956.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用Mermaid画图

1、用Mermaid画图 mermaid.md TyporaPortable.rar mermaid.zip 目录1 Mermaid是什么1.1 概述1.2 网址官网地址:Github地址:图形图形几种图形名字节点与无名字节点设置样式:style, classDef, class, :::线条图形连线(--)及注释(%%)线条样式实线与虚线箭头实线与粗实线及箭头延…

【RabbitMQ】图解

你是一个程序员,假设你维护了两个服务 A 和 B。 A 服务负责转发用户请求到 B 服务,B 服务是个算法服务,GPU 资源有限,当请求量大到 B 服务处理不过来的时候,希望能优先处理会员用户的请求。 那么问题就来了,如果普通用户和会员用户同时发起请求,怎样才能做到会员优先呢?…

THREE.js学习笔记8——Textures

这个小节主要学习纹理,Texture 纹理是覆盖几何形状表面的图像,不同类型的纹理具有多种不同的效果。 这些纹理(尤其是金属性和粗糙度)遵循PBR原则基于物理的渲染 许多技术往往遵循现实生活中的方向以获得现实的结果 成为现实渲染的标准 许多软件、引擎和库都在使用它如何加载…

快速傅里叶变换总结

基本概念 对于求和式 \(\sum a_ix^i\),如果是有限项相加,称为多项式,记作 \[f(x)=\sum_{i=0}^n a_ix^i。 \]其中最高次项的次数为 \(n\),为 \(n\) 次多项式。 用 \(n+1\) 个点可以唯一地确定一个 \(n\) 次多项式,这一过程可以参考 拉格朗日插值。 引入 给定多项式 \(f(x),…

寒假学习1

老年人评估系统 初步整理web端思路先写了第一张信息表并搭建基本框架并编写了老年人信息添加功能

1.17安卓测试

今天在idea进行安卓虚拟机测试成功,昨天的错误是因为版本不兼容 启动虚拟机运行测试

【Azure APIM】升级中国区APIM服务 stv1 到 stv2 遇见错误

Invalid parameter: This Migration API option is not supported or is temporarily disabled due to internal issues. Please visit https://aka.ms/apim-migrate-stv2 to see other migration options.问题描述 在执行Azure API Management服务升级的操作中 (从 stv1 升级到…

高频面题: 你们线上 QPS 多少?你 怎么知道的?

本文原文链接 文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 :《尼恩Java面试宝典》 持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备 免费赠送 :《尼恩技术圣经+高并发系列PDF》 ,帮你 …

【Java安全】CB链详细分析

免责申明: 本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法.环境配置 pom.xml添加: <dependency> <groupId>commons-beanutils</groupId> <artifactId>commo…

17-php相关知识

1、安装最新版phpstudy集成工具并创建一个网站,编写php代码输出网站信息(phpinfo)利用小皮创建一个名叫pikachu的网站,根目录为pikachu源码存放的目录在根目录下的test目录中创建info.php文件(内容为<?php phpinfo;?>)浏览器访问该地址,输出pikachu网站对应的ph…

ljnljn的春秋杯冬季赛wp(1.17)

杂项 1、See anything in these pics? 压缩包里有个码,确认是aztec码这个是压缩包密码,解压出一张图片 binwalk找到多个图片,foremost分离 1:JPEG image data, JFIF standard 1.01 2:PNG image, 360 x 450, 8-bit grayscale, non-interlaced 3:TIFF image data, big-endian…

金融行业构建高效知识库:策略与实践

在金融行业,信息的准确性和时效性至关重要。随着业务范围的扩大和产品线的丰富,金融机构面临着前所未有的知识管理挑战。一个高效、易用的内部知识库不仅能够提升员工工作效率,还能增强客户服务质量,促进业务创新。本文将提供一套快速搭建金融行业内部知识库的指南,并简要…