You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 10:54:20