PyQt入门(11)-操作数据库

目录

一、简介

二、QSqlDatabase

1、创建数据库连接

2、PyQt支持的数据库类型

3、添加mysql驱动

三、QSqlQuery

1、创建查询并执行Sql语句

2、判断执行结果

3、定位到有效的记录上

4、获取记录的值


一、简介

操作数据库的标准流程是:

1、建立数据库连接

2、使用SQL语句做增删改查

3、关闭数据库连接

在PyQt中,数据库连接由QSqlDatabase提供,sql语句的执行则由QSqlQuery负责。

二、QSqlDatabase

一个QSqlDatabase的实例就代表一个到数据库的连接,这个连接通过数据库驱动来访问数据库,在PyQt中,数据库驱动是QSqlDriver(一个抽象类)子类的一个实例。除非是开发自己的数据库驱动,不然在应用上一般是不会用到QSqlDriver的。

QSqlDatabase的完整介绍及API见:QSqlDatabase详细说明

1、创建数据库连接

创建一个数据库连接一般是通过调用QSqlDatabase的静态方法addDatabase()来实现的:

@staticmethod 
def addDatabase(type: str,
                connectionName: str = ...) -> QSqlDatabase
'''
type: 数据库类型
connectionName: 这个连接的名字,如果不传这个连接就是应用的默认数据库连接
'''

示例:
db = QSqlDatabase.addDatabase('QMYSQL')
db.setHostName('127.0.0.1')
db.setPort(3306)
db.setDatabaseName('course')
db.setUserName('root')
db.setPassword('123456')
# 打开数据库连接
db.open()

2、PyQt支持的数据库类型

类型名(用于addDatabase type参数)对应数据库
QDB2IBM DB2 (version 7.1 and above)
QIBASEBorland InterBase
QMYSQL / MARIADBMySQL or MariaDB (version 5.0 and above)
QOCIOracle Call Interface Driver
QODBCOpen Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases
QPSQLPostgreSQL (versions 7.3 and above)
QSQLITESQLite version 3

3、添加mysql驱动

 QT的sql模块是把数据库驱动作为插件来使用的,而不是集成到qt环境中,所以如果qt环境中缺少某个数据库驱动的话,是无法连接到这个数据库的。

QSqlDatabase的静态方法drivers()可以用于列出当前可用的数据库驱动:

目前所用的pyqt和qt版本

PyQt6      6.5.0
PyQt6-Qt6  6.5.1

默认就带有的数据库驱动:

print(QSqlDatabase.drivers())
'''
['QSQLITE', 'QODBC', 'QPSQL']
'''

可以看到,默认是不带mysql驱动的。

MySQL驱动可以下载qt源码自己编译,也可以去网上找现成的库,我没有qt的环境,编译不了,这里推荐一个github链接,里面有各个版本的qt对应的MySQL驱动:MySql驱动 

一定要下载和自己的qt版本一样的mysql驱动,不然驱动是用不了的。

这边下载了qsqlmysql.dll_Qt_SQL_driver_6.5.1_MSVC2019_64-bit.zip,解压后:

 qsqlmysqld.dll是debug版本,qsqlmysql.dll是release版本,这里就用release版本。

先把qsqlmysql.dll拷贝到qt的驱动目录下:

然后再把 libmysql.dll拷贝到qt的bin目录下:

这里要说明一下,本机安装的是mysql8,其所用的openssl库是1.1版本的, 所以跟libmysql.dll一块拷到bin目录下的openssl库要用1.1版本的,而不能用下载的包里面的3版本的,否则就会报

SSL connection error: unknown error number QMYSQL: Unable to connect 错误。

三、QSqlQuery

一旦用QSqlDatabase创建好数据库连接并打开之后,就可以用这个连接来创建一个QSqlQuery实例,后面的数据库操作都是在这个QSqlQuery实例之上进行。详细见:QSqlQuery官方文档

1、创建查询并执行Sql语句

首先,要创建一个QSqlQuery实例

构造函数:
QSqlQuery(query: str = '', db: QSqlDatabase = QSqlDatabase())
'''
query:要执行的SQL语句,如果传递了sql语句,则在实例化QSqlQuery对象的时候就会
自动执行这条sql语句,后面就不再需要调用exec()了。
db: 数据库连接,不传则使用应用默认的数据库连接(如果有的话)
'''

 其次,如果在创建QSqlQuery实例的时候没有传Sql语句,那就需要调用exec()来执行sql语句。

1、把sql语句直接传递给exec()

query = QSqlQuery()

query.exec("SELECT * FROM artist")

while(query.next()){

        doSomething();

}

2、先用prepare()准备sql语句,然后调用exec()执行

query = QSqlQuery()

query.prepare("SELECT * FROM artist")

query.exec()

while(query.next()){

        doSomething();

}

简单的sql语句就直接用exec()执行就行了,prepare()主要是配合bindValue()来实现绑定值的。

sql语句一般都是有筛选条件(where)的,而筛选所用的值很少有直接给出,一般都在程序变量中,这时候我们就要先用prepare()准备sql语句并提供占位符,然后用bindValue()把占位符和变量绑定,实现把变量的值传递给sql语句,从而让QSqlQuery执行。

Oracle数据库通过使用冒号名称语法来识别占位符,例如:name。ODBC只是使用?字符。Qt支持这两种语法,但有一个限制,即不能将它们混合在同一个查询中。

我们姑且把 :name 称为具名占位符成为匿名占位符

bindValue()有两个函数签名:

bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType = QSql::In)
'''
通过名称来给占位符绑定值,该方法需要指定名字,所以只有具名占位符可用
'''

bindValue(int pos, const QVariant &val, QSql::ParamType paramType = QSql::In)
'''
通过位置来给占位符绑定值,具名占位符和匿名占位符均可用
'''

下面看示例: 

# 具名占位符
query.prepare("select * from tb_product where prod_name=:name and prod_price=:price")

query.bindValue(0, '苹果')
query.bindValue(1, '8.89')

# 注意 :(冒号)不能少,即 :name 一起才是一个占位符
query.bindValue(":name", '苹果')
query.bindValue(":price", '8.89')

对于具名占位符 :name和:price来说,上面这两种绑定值的方式都可以
# 匿名占位符
query.prepare("select * from tb_product where prod_name=? and prod_price=?")
# 匿名占位符只能通过这种方式绑定值
query.bindValue(0, '苹果')
query.bindValue(1, '8.89')

2、判断执行结果

成功执行了一条SQL语句的话,查询会处于活动状态,即 isActive() 会返回True。

对于增、删、改来说,可以通过 numRowsAffected() 来判断生效的记录数。

对于查询来说,可以通过 size() 来得到查询出的记录数。

下面是两个示例:

#插入
query.exec("insert into tb_product values(NULL, '冬枣', 9.89, '冬枣很好吃,我喜欢吃')")
if query.isActive():
    print(self.sql_query.numRowsAffected())
else:
    print("insert fail:", query.lastError().text())

#查询
query.prepare("select * from tb_product where prod_name=? and prod_price=?")
query.bindValue(0, '苹果')
query.bindValue(1, '8.89')
query.exec()
if query.isActive():
    print(query.size())
    while query.next():
        for i in range(query.record().count()):
            print(query.value(i), end='   ')
            print('')
else:
    print("select fail:", query.lastError().text())

3、定位到有效的记录上

对于查询出的结果集来说,我们想访问某条记录,那必须先定位到这条记录,然后才能获取。

QSqlQuery()提供了几个方法用于定位记录:

next():定位到下一条记录上,如果当前已是最后一条记录,该方法返回False,否则返回True
previous():定位到上一条记录上,如果当前是第一条记录,该方法返回False,否则返回True
first():定位到第一条记录上
last():定位到最后一条记录上
seek(int index, bool relative = false):定位到指定记录上
'''
如果relative为False(默认),则seek()遵循以下规则:
如果index为负数,query会定位到第一条记录之前,并且seek返回False;
否则,query尝试定位到index指定的记录处,失败则定位到最后一条记录之后并且seek返回false,成功seek则seek返回true

如果relative为True,则seek()遵循以下规则:
...
'''

4、获取记录的值

获取记录的值通过 value() 方法,可以传入索引获取,也可以传入列名获取。

那要怎么指定列名呢,我们并不总是指定数据库表结构的,可以通过record()方法获取QSqlRecord,这是一个对查询集的一个数据库描述,从里面获取列名,下面通过一个代码示例来说明:

# 准备sql语句并使用占位符
self.sql_query.prepare("select prod_name as name, prod_price as price from tb_product where prod_name=? and prod_price=?")

# 匿名索引只能通过位置来绑定值
self.sql_query.bindValue(0, '苹果')
self.sql_query.bindValue(1, '8.89')

# 执行sql语句
self.sql_query.exec()

# 判断执行是否成功
if self.sql_query.isActive():
    # 打印查询到的记录数
    print(self.sql_query.size())

    # 拿到record
    record = self.sql_query.record()

    # 打印出列名
    for i in range(record.count()):
        print(record.field(i).name(), end='   ')
    print('')

    # 从结果集中取值
    while self.sql_query.next():
        for i in range(record.count()):
            # 这里我们还是通过索引来取值
            print(self.sql_query.value(i), end='   ')
        print('')
else:
    # 如果sql执行失败则打印出来失败描述
    print("select fail:", self.sql_query.lastError().text())

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在PyQt5中,可以使用QSqlDatabase类来连接数据库。首先,需要使用addDatabase方法设置连接数据库数据库驱动类型,然后使用setDatabaseName方法设置所连接的数据库名称。如果需要指定数据库所在的主机名称、连接的用户名和密码,可以使用setHostName、setUserName和setPassword方法进行设置。在执行完SQL语句后,如果没有其他数据库操作,需要使用db.close方法关闭数据库连接,因为数据库连接资源是有限的,不再使用的数据库连接必须关闭,否则数据库连接资源最终会被耗尽,导致程序无法正常连接数据库。\[1\] 另外,QSqlDatabase类还有其他常用方法,例如commit方法用于提交事务,如果执行成功返回True;rollback方法用于回滚数据库事务;close方法用于关闭数据库连接。\[2\] 以下是一个连接数据库的示例代码: ```python import sys from PyQt5.QtSql import QSqlDatabase from PyQt5.QtCore import * if __name__ == "__main__": app = QCoreApplication(sys.argv) db = QSqlDatabase.addDatabase("QSQLITE") db.setDatabaseName("/home/user/test.db") if db.open(): print("open DB success.") sys.exit(app.exec_()) ``` 在这个示例中,我们使用了QSqlDatabase类来连接SQLite数据库。首先,我们使用addDatabase方法设置数据库驱动类型为QSQLITE,然后使用setDatabaseName方法设置数据库名称为"/home/user/test.db"。接着,我们调用db.open方法打开数据库连接,如果打开成功,则输出"open DB success."。最后,我们使用sys.exit方法来退出应用程序。\[3\] #### 引用[.reference_title] - *1* *2* *3* [PyQt5快速入门(八)PyQt5数据库操作](https://blog.csdn.net/cdqvkn73338/article/details/100959259)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值