如何通过QSqlDatabase捕获唯一约束违反错误(适配多数据库)
Qt数据库唯一键冲突错误区分实现方案
核心思路
数据库操作报错后,通过QSqlError对象获取数据库原生错误码,结合当前加载的数据库驱动类型做分支判断,精准识别唯一键约束违反场景,和其他错误做差异化处理。不要依赖错误文本做全匹配,避免本地化语言版本差异导致判断失效。
两类数据库的识别规则
- SQLite:驱动名为
QSQLITE,约束类错误统一返回原生错误码19,唯一键冲突的错误信息固定包含UNIQUE关键字 - MS SQL Server:驱动名为
QODBC(ODBC连接方式)或QMSSQL(Qt6新增原生驱动),唯一键/唯一索引冲突对应两个固定原生错误码:2601(唯一索引重复)、2627(UNIQUE约束违反)
可复用判断函数
#include <QSqlDatabase> #include <QSqlError> #include <QString> bool isUniqueKeyConflict(const QSqlError& err, const QSqlDatabase& db) { if (err.type() == QSqlError::NoError) { return false; } const QString driver = db.driverName(); const int nativeErrCode = err.nativeErrorCode().toInt(); if (driver == "QSQLITE") { // 错误码19是通用约束冲突,匹配UNIQUE关键字排除非空、外键、检查约束等其他冲突 return nativeErrCode == 19 && err.databaseText().contains("UNIQUE", Qt::CaseInsensitive); } if (driver == "QODBC" || driver == "QMSSQL") { return nativeErrCode == 2601 || nativeErrCode == 2627; } // 未适配的数据库类型默认走普通错误逻辑 return false; }
业务层调用示例
QSqlQuery insertQuery(db); insertQuery.prepare("INSERT INTO user_info(phone) VALUES (?)"); insertQuery.addBindValue("13800138000"); if (!insertQuery.exec()) { QSqlError lastErr = insertQuery.lastError(); if (isUniqueKeyConflict(lastErr, db)) { // 唯一键冲突专属处理:比如提示手机号已注册、执行更新逻辑替代插入等 qDebug() << "提交的记录已存在,触发唯一键约束"; } else { // 其他错误通用处理:打印错误日志、返回操作失败提示等 qDebug() << "数据库操作异常:" << lastErr.text(); } }
注意事项
- SQLite判断时必须加
UNIQUE关键字校验:错误码19覆盖所有约束违反场景,不加关键字校验会把外键冲突、非空约束违反等错误误判为唯一键冲突 - 所有判断逻辑封装在独立函数内,后续如果新增其他数据库支持,只需要在函数内追加对应分支,上层业务代码不需要改动
- 不要使用
QSqlError::text()做匹配:该字段返回的是驱动拼接的组合提示,不同Qt版本格式可能存在差异,优先使用nativeErrorCode()和databaseText()做判断
内容的提问来源于stack exchange,提问作者HiddenWindshield
相关产品推荐
相关产品推荐

