Russian Qt Forum

Qt => Базы данных => Тема начата: dnc2rt от Март 05, 2010, 10:24



Название: QSqlDatabase (prepare и exec)
Отправлено: dnc2rt от Март 05, 2010, 10:24
Доброе утро!
Не удается выполнить запрос используя:

Код:
QSqlQuery query(QSqlDatabase::database("localdb"));

QString sql = "SELECT * FROM users;";

query.prepare( sql );
if( !query.exec() )
{
  QMessageBox::critical( this, QObject::tr("Fatal Error"), query.lastError().text() );
  QMessageBox::critical( this, QObject::tr("query"), query.lastQuery() );
  return;
}

В итоге, на prepare возвращает true, а вот на exec в первом сообщении выдает пустое окно (пустое окно уже обсуждалось на форуме), а во втором наш sql запрос.

Но если опустить prepare и выполнить:

Код:
QSqlQuery query(QSqlDatabase::database("localdb"));
QString sql = "SELECT * FROM users;";
if( !query.exec(sql) )
{
  QMessageBox::critical( this, QObject::tr("Fatal Error"), query.lastError().text() );
  QMessageBox::critical( this, QObject::tr("query"), query.lastQuery() );
  return;
}

То все работает, но хотелось бы, чтобы в будущем можно было использовать prepare...


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: MoPDoBoPoT от Март 05, 2010, 16:36
Странно, такого не должно быть (только что даже проверил).
Может где-то у тебя все-таки ошибка в коде?


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: dnc2rt от Март 06, 2010, 20:12
Спасибо! Значит либо ошибка в подключении mysql к Qt, может не правильно подключил, хотя exec() работает верно.
Попробую наверно переставить на другой машине все и установить mysql последний, а то сейчас он 5.0 и собирал не совсем под него...
Еще раз спасибо, попробую копнуть в другую сторону!


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: dnc2rt от Март 09, 2010, 09:21
Все, разобрался, спасибо  :D!


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: dnc2rt от Март 09, 2010, 11:59
Добрый день, похоже я с этим долго буду воевать...

Код:
QSqlQuery query(QSqlDatabase::database("localdb"));
QString sql = "SELECT name FROM users;";
query.prepare( sql );
if( !query.exec() )
{
  ***
}
int i = query.size();
while( query.next() )
{
   // Сюда не заходит, в то время как в переменную i возвращается правильное значение. (Например "4")
}

Код:
QSqlQuery query(QSqlDatabase::database("localdb"));
QString sql = "SELECT name FROM users;";
if( !query.exec(sql) )
{
  ***
}
int i = query.size();
while( query.next() )
{
   // Сюда заходит на ура, выдает наш любимый cp1251
}

Подскажите, что я делаю не так?! Вроде все правильно, и оба варианта возвращают количество результирующих записей, но ...


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: break от Март 09, 2010, 14:47
наверное query.first(); перед циклом...


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: dnc2rt от Март 09, 2010, 16:39
Вроде как перед циклом ставить смысла хорошего нет, ибо в документации по поводу QSqlQuery::next(), написано следующее:
Цитировать
if the result is currently located before the first record, e.g. immediately after a query is executed, an attempt is made to retrieve the first record
Насколько я понимаю, в данном случае QSqlQuery::first() пользы не принесет... могу ошибаться...

Кстати, prepare и последующее использование bindValue не дает необходимых результатов, т.е. если в

***.prepare( "SELECT name FROM ? ;" );
***.bindValue( 0, "groups" );
***.exec();

в ***.lastQuery() будет выдано "SELECT name FROM ? ;"... перепробовал все примеры в документации, не могу понять, в чем проблема....

Пока приходится пользоваться ***.exec( "код запроса" ); Но это очень не удобно... и QDateTime::currentDateTime я так вставить не смогу...


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: Пантер от Март 09, 2010, 17:41
lastQuery выдает запрос без биндов. Чтобы увидеть бинды, есть boundValues. К сожалению, конечный запрос (с подставленными значениями) увидеть не получится. :(


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: break от Март 09, 2010, 18:41
Цитировать
Насколько я понимаю, в данном случае QSqlQuery::first() пользы не принесет... могу ошибаться...
Пробовал? В документации действительно сказано что вроде как не надо, но вдруг баг...


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: MoPDoBoPoT от Март 09, 2010, 18:52
наверное query.first(); перед циклом...
Только не забыть про первую запись, а то можно и перепрыгнуть (while (query.next()) )...

***.prepare( "SELECT name FROM ? ;" );
***.bindValue( 0, "groups" );
***.exec();
Вообще говоря, здесь допущена ошибка. Бинды предназначены только для значений переменных, используемых в части WHERE. Подготовка запроса и связывание переменных, это целый механизм, а не тупо подстановка/замена текста в запросе. Но в твоем случае запрос прошел, потому что используемая тобой СУБД (или драйвер к ней) не поддерживает позиционное связывание (именно позиционное, т.к. bindValue(0,...)) и поэтому произошла обычная подстановка.


Название: Re: QSqlDatabase (prepare и exec)
Отправлено: dnc2rt от Март 09, 2010, 19:58
Все, надеюсь теперь буду внимательнее!

Спасибо Пантер, буду знать этот нюанс.
break, спасибо за помощь. Спасибо тебе за ответ в топике про QDateTime и prepare! Полезная новость для меня.
MoPDoBoPoT, спасибо за исчерпывающую информацию!!!

PS: еще оказалось огромную роль в том что работало не как надо даже если писать корректно - не верная сборка mysql... со старой сборкой 5.0 у меня работает не так как надо, в то время как с последней нет проблем.