在PyQt6中使用QtSql模块的QSqlQuery执行DDL语句时,有时会遇到语句返回成功但数据库结构没有任何变化的情况。本文分析该问题的常见原因并提供对应的解决方案。

问题现象
开发者调用QSqlQuery的exec()方法执行CREATE TABLE或ALTER TABLE等DDL语句,isActive()返回True,但数据库中根本找不到新建的表。代码示例如下:
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("test.db")
db.open()
query = QSqlQuery()
sql = "CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY, name TEXT)"
ok = query.exec(sql)
print("exec result:", ok)
# 有时表并未真正创建
常见原因
1. 事务未提交
部分数据库驱动在连接建立后默认关闭自动提交,DDL语句也处于事务中,必须显式提交。可调用QSqlDatabase的commit()方法。
2. 未检查执行错误
exec()返回False时,应通过lastError()查看具体信息,而不只是依赖返回值。
3. 查询未绑定到正确的数据库连接
如果程序中存在多个连接,需在构造QSqlQuery时指定连接名,否则可能使用了错误连接。
解决方案
显式提交事务
执行DDL后主动提交,确保语句生效:
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("test.db")
if not db.open():
print("open failed")
query = QSqlQuery()
ddl = "CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY, name TEXT)"
if not query.exec(ddl):
print("error:", query.lastError().text())
else:
# 显式提交,对部分驱动必要
if not db.commit():
print("commit error:", db.lastError().text())
指定连接名
当存在多个连接时,明确使用对应连接:
db = QSqlDatabase.addDatabase("QSQLITE", "conn1")
db.setDatabaseName("test.db")
db.open()
query = QSqlQuery(db) # 绑定到conn1
query.exec("CREATE TABLE t1 (id INT)")
db.commit()
排查建议
- 每次执行后打印lastError()内容
- 确认数据库文件是否被其他进程占用
- 使用命令行或专用工具打开数据库验证结构
通过上述方法,基本可以解决PyQt6中QtSql QSqlQuery执行DDL语句无效的问题。