QSqlTableModel.insertRecord()报错"No Fields to update"解决记录 && QField构造
问题的出现
当我想向一个Table中插入一条记录时,我本能的想的是:QSqlTableModel是由一条一条的Record组成的,那么我先创建一个Record,并且赋予对应的值,然后再使用QSqlTableModel::insertRecord()插入就好了,代码如下:
QSqlRecord rcd;
rcd.remove(model->fieldIndex("id"));
rcd.setValue("name", "upName");
rcd.setValue("platform", "Bilibili");
rcd.setValue("level", "Unknow");
auto status = model->insertRecord(-1, rcd);
if (status) {
model->submitAll();
} else {
qDebug() << "Last Error: " << model->lastError().text();
}
上述代码中model就是一个QSqlTableModel实例,有5个字段,分别是:id、name、platform、level、win_rate。(可以不用知晓其含义)
其中id是自增字段,level和win_rate都是可以为null的字段,name和platform是不可以为null的字段。
因为id是自增的,所以需要删除(网上查到的,事实也是如此)
执行输出:No Fields to update
问题的解决
查阅了很久发现有人这么写:
QSqlRecord rcd = model->record();
rcd.remove(model->fieldIndex("id"));
rcd.setValue("name", "upName");
rcd.setValue("platform", "Bilibili");
rcd.setValue("level", "Unknow");
auto status = model->insertRecord(-1, rcd);
if (status) {
model->submitAll();
} else {
qDebug() << "Last Error: " << model->lastError().text();
}
这个record是从model这里获取的,而不是自己创建的,试了之后发现成功了。
待了解了下面之后还有另一种办法来解决
问题的起因
如果按照第一种写法,之后再输出一下QSqlRecord,可以观察到结果为:QSqlRecord(0)
而如果按照第二种写法,之后再输出一下QSqlRecord,可以观察到结果为:
QSqlRecord(4)
0: QSqlField("name", QString, tableName: "up_info", length: 64, generated: yes, typeID: 1043, autoValue: false, readOnly: false) "upName"
1: QSqlField("platform", QString, tableName: "up_info", length: 64, generated: yes, typeID: 1043, autoValue: false, readOnly: false) "Bilibili"
2: QSqlField("level", QString, tableName: "up_info", length: 64, generated: yes, typeID: 1043, autoValue: false, readOnly: false) "Unknow"
3: QSqlField("win_rate", double, tableName: "up_info", length: 4, generated: yes, typeID: 700, autoValue: false, readOnly: false) "0"
可以发现,第一种写法,QSqlRecord里面什么都没有。查看了文档发现:If the field does not exist, nothing happens
所以可以推测出:QSqlRecord::setValue()并不会增加field。而使用model.record()
,里面是带field的。
经过进一步的查阅资料有以下总结:
- 可以简单的认为QSqlRecord是由多个QSqlField组成的一个数据结构。当QSqlRecordrd执行的操作与field相关时,如果Field没有存在,nothing happen。
- 使用QSqlTableModel向数据表中插入一条记录,可以先使用
model.record()
获取一个带有该表所有字段信息的记录,再修改字段内容再insert。这样比较方便 - 如果表中某个字段是自增的,那么QSqlRecord中需要移除该字段
- 使用QSqlRecord创建的记录也是可以插入的到表中的,可以使用QSqlRecord::append()方法先添加字段,再进行改变,再插入,相对麻烦。
PS:QSqlField构造有点坑,先看构造函数:
[explicit, since 6.0] QSqlField::QSqlField(const QString &fieldName = QString(), QMetaType type = QMetaType(), const QString &table = QString())
Qt6.0改版的QField构造函数。(网上查的好多都是以前的写法,直接报错)
坑就在指定字段类型这里,以前的写法是QVariant::String
,已经被弃用了,本以为是用QMetaType::QString
或者QMetaType::type::QString
,结果还是错误
直到看到了官方的写法QMeta::fromType<QString>()
,只有这么写才行。(麻烦)