Я использую следующий фрагмент кода для извлечения данных из базы данных SQLite с использованием Qt:
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 только в первый раз, и я не могу получить остальные строки.
Кстати, здесь я нашел аналогичный вопрос но для меня обратная итерация не работает
Ниже я помещаю весь код функции:
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());
}
Ваш код имеет одну серьезную проблему для привязки, а именно:
QSqlQuery :: QSqlQuery (const QString & query = QString (), QSqlDatabase db = QSqlDatabase ())
Создает объект QSqlQuery, используя запрос SQL и базу данных db. Если db не указан или недействителен, используется база данных приложения по умолчанию. Если запрос не является пустой строкой, он будет выполнен.
Итак, ваш запрос будет выполнен во время построения, так как он не пустой, и связывание уже слишком поздно для этого.
Я бы лично создал экземпляр с пустой строкой по умолчанию, а затем сделал бы явную подготовку согласно документация.
Итак, я бы написал что-то вроде этого:
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( )
}
Других решений пока нет …