SQLite + Qt:从表中选择始终返回单行

时间:2014-01-03 17:01:39

标签: c++ qt sqlite qtsql qsqlquery

我使用以下代码使用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字段等于所需值的行。我用sqlbrowser作为Qt演示应用程序提供了这个。但是QSqlQuery::next( )仅在第一次返回true而我无法获取其余行。

BTW,在这里我找到了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());
}

1 个答案:

答案 0 :(得分: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( )
}