Qt QODBC连接ACRON数据库时SQL_CURSOR_STATIC属性设置失败求助
问题背景
环境配置:
- 服务器A:Windows Server 2016 Standard,Qt Creator 8.0.1(C++)开发环境
- 服务器B:Windows Server 2016 Standard,部署ACRON Database(一款用于过程优化的工厂数据采集与报告系统)
问题现象
Qt程序能正常连接ACRON的ODBC驱动,但执行SELECT * FROM PV查询时抛出错误:
QSqlError("1010", "QODBC: QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration", "[DataForum][ACRON ODBC Driver]Driver not capable")
已尝试操作
- 检查ACRON数据库日志,仅记录连接关闭信息,无有效错误细节:
22.09.2022 12:29:39; INFO ACDBComu64 ODBC Driver on Server A: Connection closed remote host. (10054: recv)
- 使用PowerShell脚本连接同一DSN执行相同SQL,可正常返回数据(脚本见下文)
相关代码
Qt代码(执行失败)
#include <QCoreApplication> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlError> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QSqlDatabase db; db = QSqlDatabase::addDatabase("QODBC"); db.setDatabaseName("TestDatabase101"); //db.setConnectOptions("SQL_ATTR_ACCESS_MODE=SQL_MODE_READ_ONLY"); if(db.open()){ qDebug() << "Connected" << Qt::endl; qDebug() << db.isValid() << Qt::endl; } else qDebug() << "Error" << Qt::endl; QSqlQuery query(db); if(!query.exec("SELECT * FROM PV")) qDebug() << query.lastError() << Qt::endl; db.close(); return a.exec(); }
PowerShell脚本(执行成功)
$conn = New-Object System.Data.Odbc.OdbcConnection $conn.Connectionstring = "DSN=TestDatabase101" $conn.Open() $sql = "SELECT * FROM PV" $cmd = New-Object System.Data.Odbc.OdbcCommand($sql,$conn) $da = New-Object System.Data.Odbc.OdbcDataAdapter($cmd) $dt = New-Object System.Data.DataTable $null = $da.fill($dt) $conn.Close() $dt
解决方案
问题核心是Qt的QODBC驱动默认尝试设置SQL_CURSOR_STATIC游标属性,但ACRON的ODBC驱动不支持该属性;而PowerShell的OdbcCommand默认使用的SQL_CURSOR_FORWARD_ONLY游标是驱动兼容的。
方案1:为单个查询设置兼容的游标类型
在执行SQL前,显式将QSqlQuery的游标类型设为ForwardOnly,这是多数轻量ODBC驱动支持的类型:
QSqlQuery query(db); // 设置游标为仅向前遍历,对应ODBC的SQL_CURSOR_FORWARD_ONLY query.setForwardOnly(true); if(!query.exec("SELECT * FROM PV")) { qDebug() << query.lastError() << Qt::endl; } // 遍历查询结果 while(query.next()) { // 示例:获取第一列数据 qDebug() << query.value(0).toString(); }
方案2:全局设置连接的游标属性
如果需要所有查询都使用兼容的游标,可以在数据库连接时添加ODBC选项,强制指定游标类型:
db = QSqlDatabase::addDatabase("QODBC"); db.setDatabaseName("TestDatabase101"); // 添加连接选项,指定游标类型为SQL_CURSOR_FORWARD_ONLY db.setConnectOptions("SQL_ATTR_CURSOR_TYPE=SQL_CURSOR_FORWARD_ONLY"); if(db.open()){ qDebug() << "Connected" << Qt::endl; qDebug() << db.isValid() << Qt::endl; } else { qDebug() << "Error" << Qt::endl; }
验证说明
以上两种方式均避免了Qt尝试设置驱动不支持的SQL_CURSOR_STATIC属性,改用驱动兼容的游标类型,测试后可正常执行SQL查询并获取数据。
内容的提问来源于stack exchange,提问作者Daniel B

