QSqlTableModel::setRecord未修改行反而插入新行的问题求助
Qt5 QSqlTableModel::setRecord 触发插入新行而非更新的问题解决
问题重现
调用QSqlTableModel::setRecord试图更新指定ID的Protocol记录名称时,却插入了一条带新ID和默认名称的重复行;移除setGenerated调用后,setRecord直接返回false。对应ID的记录确实存在且非空。
修复后的代码
bool ProtocolRepository::update(const Protocol& protocol) { auto record = model->record(protocol.id); if (record.isEmpty()) { return false; } record.setValue("name", protocol.name); // 仅标记主键id为非生成,避免Qt自动修改主键值 record.setGenerated("id", false); if (!model->setRecord(protocol.id, record)) { qDebug() << "setRecord失败:" << model->lastError().text(); return false; } bool submitSuccess = model->submitAll(); if (!submitSuccess) { qDebug() << "submitAll失败:" << model->lastError().text(); } return submitSuccess; }
关键修复点说明
移除
name字段的setGenerated(false)
你之前对name设置非生成标记,导致Qt生成更新语句时会忽略这个字段,相当于没有任何修改操作。此时如果主键处理存在歧义,Qt会误将操作判定为插入新行。确保Model正确初始化
必须保证QSqlTableModel正确关联表、设置编辑策略并加载数据,否则会导致主键识别失败,引发更新逻辑异常:// 示例初始化代码 model = new QSqlTableModel(this); model->setTable("protocols"); model->setEditStrategy(QSqlTableModel::OnManualSubmit); // 匹配手动提交逻辑 model->setPrimaryKey(model->fieldIndex("id")); // 显式指定主键,避免自动识别失败 model->select(); // 加载表数据处理
updated_date自动更新
你的表结构中updated_date设为非空且默认当前时间,但Qt默认会尝试在更新时覆盖该字段,导致因未提供值而失败。可以通过两种方式解决:- 数据库触发器自动更新(推荐):
之后在代码中给CREATE TRIGGER IF NOT EXISTS update_protocols_updated_date AFTER UPDATE ON protocols FOR EACH ROW BEGIN UPDATE protocols SET updated_date = CURRENT_TIMESTAMP WHERE id = OLD.id; END;updated_date添加非生成标记:record.setGenerated("updated_date", false); - 手动设置当前时间:
record.setValue("updated_date", QDateTime::currentDateTime());
- 数据库触发器自动更新(推荐):
错误排查技巧
当setRecord或submitAll返回false时,务必通过model->lastError().text()打印具体错误信息,这能快速定位是字段约束问题、主键识别问题还是SQL语法问题。
内容的提问来源于stack exchange,提问作者Dmitry Sudorgin
相关产品推荐
相关产品推荐

