如何获取QSqlQuery中批量执行的预处理查询语句?
解决QSqlQuery execBatch()绑定QVariantList时的完整SQL生成问题
对于使用execBatch()结合QVariantList批量插入的场景,旧方案无法完整展示所有绑定值,这里提供一个直接生成对应完整SQL的实现:
辅助函数实现
我们可以封装一个函数,根据已准备的SQL和绑定的QVariantList,生成展开后的批量SQL:
#include <QSqlQuery> #include <QStringList> #include <QVariant> QString getBatchExecutedSql(const QSqlQuery &query) { QString originalSql = query.lastQuery(); const QList<QVariant> &bindValues = query.boundValues(); // 提取所有占位符的位置 QList<int> placeholderPositions; int pos = 0; while ((pos = originalSql.indexOf('?', pos)) != -1) { placeholderPositions.append(pos); pos++; } // 校验绑定值是否为QVariantList且长度统一 int batchSize = 0; for (const QVariant &val : bindValues) { if (val.type() != QVariant::List) { return originalSql; } QVariantList list = val.toList(); if (batchSize == 0) { batchSize = list.size(); } else if (batchSize != list.size()) { return originalSql; } } if (batchSize == 0) { return originalSql; } // 生成每一行的SQL片段 QStringList rowSqls; for (int i = 0; i < batchSize; ++i) { QString rowSql = originalSql; // 逆序替换占位符,避免替换后位置偏移 for (int j = placeholderPositions.size() - 1; j >= 0; --j) { int pos = placeholderPositions[j]; QVariant val = bindValues[j].toList().at(i); QString valStr; // 根据数据类型处理字符串表示(适配常见类型) switch (val.type()) { case QVariant::String: case QVariant::Date: case QVariant::DateTime: valStr = QString("'%1'").arg(val.toString().replace("'", "''")); break; case QVariant::Int: case QVariant::LongLong: case QVariant::Double: valStr = val.toString(); break; default: valStr = "NULL"; break; } rowSql.replace(pos, 1, valStr); } rowSqls.append(rowSql); } // 合并为完整的批量执行SQL return rowSqls.join(";\n"); }
使用示例
QSqlQuery query; query.prepare("insert into a (b, c) values (?, ?)"); QVariantList qvariantlist1; qvariantlist1 << "val1" << "val2" << "val3"; QVariantList qvariantlist2; qvariantlist2 << 1 << 2 << 3; query.addBindValue(qvariantlist1); query.addBindValue(qvariantlist2); query.execBatch(); // 输出完整的批量执行SQL qDebug() << getBatchExecutedSql(query);
说明
- 函数会自动校验绑定值的合法性,仅在所有绑定值为等长QVariantList时生成展开SQL
- 针对不同数据类型做了基础的转义处理,避免SQL语法错误
- 仅建议用于调试场景,生产环境仍需使用绑定参数防止SQL注入
- 若需适配特殊数据库类型(如PostgreSQL数组),可扩展类型处理分支
内容的提问来源于stack exchange,提问作者user18197583
相关产品推荐
相关产品推荐

