Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > ошибка при выполнении запроса


Автор: chesterfielda 30.7.2009, 11:40
Добрый день, работаю с БД
почему-то на запрос 
Код

int auct_id=2;
model->setQuery("SELECT zakazchik.id,LPU.Name_LPU,LPU.INN,LPU.KPP,LPU.OGRN "
        "FROM zakazchik INNER JOIN LPU ON zakazchik.rf_LPUID=LPU.Cod "
        "WHERE zakazchik.rf_auctID="+auct_id+"");

выдает ошибку:
             error: invalid operands of types `const char*' and `const char[1]' to binary `operator+'
но если написать 
Код

QSting auct_id=2;
model->setQuery("SELECT zakazchik.id,LPU.Name_LPU,LPU.INN,LPU.KPP,LPU.OGRN "
        "FROM zakazchik INNER JOIN LPU ON zakazchik.rf_LPUID=LPU.Cod "
        "WHERE zakazchik.rf_auctID="+auct_id+"");

то все работает
и как быть??все-таки zakazchik.rf_auctID числовое поле,а не строковое

Автор: Romikgy 30.7.2009, 12:06
C++ не умеет сам приводить типы
сделай что то типа 
 
Код

int auct_id=2;
char str[200]={0};
sprintf(str,"%d",(auct_id));
QSting squery="SELECT zakazchik.id,LPU.Name_LPU,LPU.INN,LPU.KPP,LPU.OGRN "
        "FROM zakazchik INNER JOIN LPU ON zakazchik.rf_LPUID=LPU.Cod "
        "WHERE zakazchik.rf_auctID="+str+"";

model->setQuery(squery);

Автор: SABROG 30.7.2009, 12:37
Код

int auct_id=2;
model->setQuery(QString("SELECT zakazchik.id,LPU.Name_LPU,LPU.INN,LPU.KPP,LPU.OGRN "
        "FROM zakazchik INNER JOIN LPU ON zakazchik.rf_LPUID=LPU.Cod "
        "WHERE zakazchik.rf_auctID=%0").arg(auct_id));


Код

int auct_id=2;
QSqlQuery query;
query.prepare("SELECT zakazchik.id,LPU.Name_LPU,LPU.INN,LPU.KPP,LPU.OGRN "
        "FROM zakazchik INNER JOIN LPU ON zakazchik.rf_LPUID=LPU.Cod "
        "WHERE zakazchik.rf_auctID=?");
query.addBindValue(auct_id);
model->setQuery(query);

Автор: ecspertiza 30.7.2009, 15:54
В принципе уже всё написано но можно ещё и так

Код

int auct_id=2;
model->setQuery("SELECT zakazchik.id,LPU.Name_LPU,LPU.INN,LPU.KPP,LPU.OGRN "
        "FROM zakazchik INNER JOIN LPU ON zakazchik.rf_LPUID=LPU.Cod "
        "WHERE zakazchik.rf_auctID="+QString::number(auct_id)+"");

 

Автор: Любитель 30.7.2009, 16:27
Самый правильный вариант - второй. Заниматся конкатенцией SQL-а из строк (когда достаточно параметризованного запроса) - это извращение. Единственное - в зависимости от СУБД синтаксис задания параметров (в SQL запросе) может различаться.

Автор: SABROG 30.7.2009, 16:35
Кроме того с конкатенацией строк возникает "дыра" - SQL Injection.

Автор: Любитель 30.7.2009, 17:46
В общем случае нет. Что возникает всегда - проблема читабельности кода и снижение производительности.

Автор: SABROG 30.7.2009, 20:50
Цитата(Любитель @ 30.7.2009,  17:46)
В общем случае нет. Что возникает всегда - проблема читабельности кода и снижение производительности.

Это смотря какой общий случай. Если доступ к базе данных разграничен средствами программы, а не SQL сервера, то у "знающих" пользователей могут появится права, которых быть не должно. Например у меня на работе программа (не моя) предоставляет возможность управлять бухгалтерией, просматривать и редактировать историю действий (кто во сколько зашел в программу, чего делал на протяжении всего дня, когда завершил работу и т.п.), проставлять специальный аттрибут на заявки типа "оплачено", естественно у обычных пользователей нет возможности открывать формы с таблицами где идет работа с такими данными. Это, в первую очередь, финансовый вопрос, куда обычные сотрудники не должны лезть или даже видеть.

В общем, не зависимо от программы, лучше взять за правило не конкатенировать строки для создания SQL запросов. А если выбора нет, то читать на тему экранирования управляющих символов к конкретной БД SQL и валидации введеных данных.

Автор: Любитель 30.7.2009, 21:58
Да эт всё понятно.. В запросе топикстартера инъекции неоткуда взяться smile Ибо значение зашито в коде. А так - зависит от того, контролируется ли значение пользователем или нет. Ну и плюс действительно есть и олдскульные методы борьбы путём экранирования.

Если я говорю, что "в общем случае нет" - значит существуют случаи, когда это не так smile

Впрочем ладно - идём дальше. Нормальных ORM на С++ нет, да и вряд ли будут. Поэтому запросы так или иначе пишутся в 99% случаев явно. Но (!) запросы в коде - это тоже зло. В любом виде. С точки зрения maintainability. Поэтому, для достаточно крупногго проекта лучше использовать хранимки smile Впрочем, для маленьких приложений - достаточно вынести в ресурсы или даже просто в отдельный файл. 

Автор: SABROG 30.7.2009, 23:00
Цитата(Любитель @  30.7.2009,  21:58 Найти цитируемый пост)
достаточно вынести в ресурсы или даже просто в отдельный файл.

Я так и делаю обычно. Плохо только то, что приходится изобретать велосипед в виде формата такого файла. Конечно врятли кто будет писать серьезное приложения с использованием sqlite, но он хранимки не поддерживает (по крайней мере пару лет назад не держал, как щас не знаю). Но даже если использовать хранимые процедуры, то им же надо параметры передавать, а это опять формирование SQL запроса.

Автор: Любитель 30.7.2009, 23:15
Цитата(SABROG @  30.7.2009,  23:00 Найти цитируемый пост)
по крайней мере пару лет назад не держал, как щас не знаю

SQLite3 не поддерживает точно и не будет. Если там когда-то хранимки и будут (хотя ИМХО SQLite не для того придумывали), то это повлечёт изменение мажорного номера версии.

Цитата(SABROG @  30.7.2009,  23:00 Найти цитируемый пост)
то им же надо параметры передавать, а это опять формирование SQL запроса. 

Да не, это понятно. Просто запрос тривиален - такой запрос вполне можно пихать прямо в код. Всё бизнес-логика запроса в самой хранимке.

А вообще - мы отвлеклись от темы. Я, конечно, не против этой темы, просто тема топика была более узкая. Если кому-то интересно продолжить эту тему - вынесу в отдельный топ.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)