【问题标题】:SQLite+Qt: Select from table always returns single rowSQLite+Qt:从表中选择总是返回单行
【发布时间】:2014-01-21 10:22:01
【问题描述】:

我使用以下代码使用 Qt 从 SQLite DB 获取数据:

QSqlQuery wordQuery( QString( "SELECT id, word FROM Words WHERE ref_id = :ref_id" ) );
wordQuery.bindValue( ":ref_id", refId );
wordQuery.setForwardOnly( true );
wordQuery.exec( );

while( wordQuery.next( ) ) {
    // obtain data from `wordQuery` using QSqlQuery::value( )
}

Words 表确实包含 ref_id 字段等于所需值的行。我已经使用作为 Qt 演示应用程序提供的 sqlbrowser 进行了检查。但是QSqlQuery::next( ) 仅在第一次返回 true,我无法获取其余行。

顺便说一句,我在这里找到了similar question,但对我来说向后迭代不起作用

下面我放了整个函数代码:

QList<Word> LyricsMasterModel::fetchWords( const DbId &refId )
{
QList<Word> result;

if ( !db.isOpen( ) && !db.open( ) ) {
    return result;
}

QSqlQuery wordQuery;
wordQuery.setForwardOnly( true );
wordQuery.prepare( QString( "SELECT id, word FROM %1 WHERE ref_id = :ref_id" )
    .arg( WORDS_TABLE_NAME ) );
wordQuery.bindValue( ":ref_id", refId );
if ( !wordQuery.exec( ) ) {
    qDebug( ) << "SQL QUERY ERROR:" << wordQuery.lastError( ).text( );
}

const QSqlRecord wordTuple = wordQuery.record( );
const int idIndex = wordTuple.indexOf( "id" );
Q_ASSERT( -1 != idIndex );
const int wordIndex = wordTuple.indexOf( "word" );
Q_ASSERT( -1 != wordIndex );

while (wordQuery.next()) {
    Word word;

    word.setId( wordQuery.value( idIndex ).toByteArray( ) );
    word.setSongId( refId );
    word.setWord( wordQuery.value( wordIndex ).toString( ) );

    result << word;
}

db.close( );
return result;
}

解决方案:我没有找到问题的原因,但以下变体似乎是有效的变体:

QSqlQuery wordQuery;
wordQuery.prepare( QString( "SELECT id, word FROM %1 WHERE ref_id = :ref_id" )
    .arg( WORDS_TABLE_NAME ) );
wordQuery.bindValue( ":ref_id", refId );
const bool res = wordQuery.exec( );
Q_ASSERT( res );

if ( wordQuery.last( ) ) {
    do {
        // do stuff
    } while (wordQuery.previous());
}

【问题讨论】:

  • @LaszloPapp,不,我不是。但如果我使用wordQuery.exec( "SELECT id, word FROM Words WHERE ref_id = 1" ); 并在查询字符串中设置ref_id 参数,则根本没有结果行,即QSqlQuery::next( ) 在第一次调用时返回false。

标签: c++ qt sqlite qtsql qsqlquery


【解决方案1】:

您的代码有一个主要的绑定问题,即:

QSqlQuery::QSqlQuery(const QString & query = QString(), QSqlDatabase db = QSqlDatabase())

使用 SQL 查询和数据库 db 构造一个 QSqlQuery 对象。如果 db 未指定或无效,则使用应用程序的默认数据库。如果查询不是空字符串,就会被执行。

因此,您的查询将在构造期间执行,因为它不是空的,并且绑定已经太迟了。

我会亲自用空字符串作为默认值来构造实例,然后按照documentation 进行显式准备。

所以,我会这样写:

QSqlQuery wordQuery();
wordQuery.setForwardOnly(true);
wordQuery.prepare("SELECT id, word FROM Words WHERE ref_id = :ref_id");
wordQuery.bindValue(":ref_id", refId);
if (!wordQuery.exec())
    qDebug() << "SQL QUERY ERROR:" << wordQuery.lastError().text();

while (wordQuery.next()) {
    // obtain data from `wordQuery` using QSqlQuery::value( )
}

【讨论】:

  • 它仍然返回一行:(
  • @Ivan:你的意思是你没有得到任何错误,并且 exec() 成功了吗?你能显示你的 refId 和你希望返回的行吗?您还可以展示您的 while 循环的内部结构吗?错误必须在其他地方,而不是在这段代码中......
  • @Ivan:让我重复第三次,请告诉我们执行是否成功,如果没有,请告诉我们错误消息。此外,记录 sn-p 是没有实际意义的,因为 value() 可以接受一个字符串就好了。
  • exec() 返回真
  • @Ivan:如果你从我的代码中删除 wordQuery.setForwardOnly(true); 会发生什么?你拒绝提供一个自包含的sn-p,而你责怪Qt? :)
猜你喜欢
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-26
  • 1970-01-01
相关资源
最近更新 更多