Russian Qt Forum

Программирование => Базы данных => Тема начата: chagovets от Март 12, 2012, 16:50



Название: MSSQL 2005 Хранимая процедура
Отправлено: chagovets от Март 12, 2012, 16:50
MSSQL 2005, Qt 4.8, QODBC
Имеется хранимая процедура простого содержания:
Код:
select field1,field2 from SomeTable

Отрабатывает без проблем.
Изменяю текст процедуры на:
Код:
if 3=3
select field1,field2 from SomeTable

(IF 3=3 для примера, на самом деле любая проверка)
Ошибок запроса нет, но и результата на клиенте нет тоже.
При попытке тут же повторить запрос ответ "Подключение занято".

[Microsoft][ODBC SQL Server Driver]Подключение занято до получения результатов для другого hstmt QODBC3: Unable to execute statement


При этом другой клиент (не Qt) через ODBC в обоих случаях результат получает.
В чём может быть проблема?




Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: Rem Norton от Март 13, 2012, 13:12
на чем чаще всего спотыкаются: чтобы получить данные из хранимой процедуры MSSQL надо QSqlQuery сказать setForwardOnly(true).
Чтобы корректно отпустить HSTMT надо сделать QSqlQuery::finish();

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


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: chagovets от Март 13, 2012, 14:04
надо QSqlQuery сказать setForwardOnly(true).
Чтобы корректно отпустить HSTMT надо сделать QSqlQuery::finish();
да говорил и то и другое :)

проект прикладываю
там же скрипты ХП и таблицы


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: Rem Norton от Март 14, 2012, 00:05
Ошибка в этом:
Код
C++ (Qt)
viewModel->setQuery(*mainQuery);
 

Точнее не то, чтобы ошибка, скорее "фича" Qt.
Дело в том, что QSqlQueryModel не работает с forward-only запросами.


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: chagovets от Март 14, 2012, 08:58
Цитата: Rem Norton

QSqlQueryModel не работает с forward-only запросами.

Хорошо.
Но вот только одно "но" - как только я убираю управляющую конструкцию в хранимой процедуре (или IF или SET NOCOUNT),
то всё работает замечательно.
И ещё - я провёл аналогичный эксперимент с Adaptive Server Anywhere 8.02 (Sybase ASA) через тот же QODBC с аналогичной процедурой - всё отлично отрабатывает.


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: Rem Norton от Март 14, 2012, 19:32
Ок, тогда сделай так:
Код
C++ (Qt)
viewModel->setQuery(*mainQuery);
qDebug() << viewModel->lastError().text();
 

и посмотри, что напишет в консоли.


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: Странник от Март 14, 2012, 21:24
наступал на такую граблю, долго бился. выполнение хранимой процедуры прерывалось на середине - и ни ошибок, ни результата. что помогло сейчас помню очень смутно, вроде на форуме где-то была тема. и завтра на работе код поковыряю.


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: chagovets от Март 16, 2012, 13:45
Цитата: Rem Norton
Код
C++ (Qt)
qDebug() << viewModel->lastError().text();
 
и посмотри, что напишет в консоли.
"Forward-only queries cannot be used in a data model"

Так всё таки - при отключении управляющих конструкций результат перестаёт быть forward-only?
При чём настройка setForwardOnly(true) игнорируется...
Или как?
Почему тогда с ASA 8.02 через QODBC нет ни каких проблем?

Цитата: Странник
что помогло сейчас помню очень смутно
очень бы хотелось найти объяснение...


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: Rem Norton от Март 17, 2012, 01:56
При отключении управляющих конструкций процедура перестает быть T-SQL. И дело не в ODBC, а в MS SQL.


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: chagovets от Апрель 13, 2012, 11:45
Спустя ровно месяц удалось вернуться к вопросу :)

Цитата: Rem Norton
QSqlQueryModel не работает с forward-only запросами.
Сделал я собственную модель...
В общем проблема осталась.
Дело не в forward-only.
MS SQL не возвращает результат, точнее numRowsAffected() равен -1  - "cannot be determined"

Цитата: Rem Norton
При отключении управляющих конструкций процедура перестает быть T-SQL.

Не хочу спорить - но хранимая процедура MS SQL в любом случае T-SQL (ну или тот диалект, который используется конкретным сервером, скажем PL/SQL или Watcom).
И как бы управляющие конструкции в виде IF'ов и прочего и есть собственно язык SQL.

Цитата: Rem Norton
И дело не в ODBC, а в MS SQL.

И получается, похоже по всему, что проблема таки в QODBC.
Поскольку именно QODBC прослойка к основному ODBC и тот же Visual FoxPro не имеет проблем с получением результата от сервера не смотря на наличие или отсутствие управляющих конструкций.

Для тех, кто хочет как-то разобраться в ситуации, прикладываю проект.


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: Странник от Апрель 13, 2012, 15:02
проверил на MS SQL 2005, драйвера SQL Server и SQL Native Client, Qt 4.8.1. хранимая процедура выполняется и возвращает верный результат. минимальный рабочий пример:
Код:
QSqlQuery sqlQuery;
sqlQuery.prepare("{CALL teststoreproc (?)}");
sqlQuery.addBindValue(2);
sqlQuery.exec();
проект пока не смотрел, просто создал таблицу и хранимую процедуру из сценариев.


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: chagovets от Апрель 13, 2012, 16:48
Цитата: Странник
хранимая процедура выполняется и возвращает верный результат
в смысле exec отрабатывает без ошибки или видны результаты запроса?
и if 3=3 в коде процедуре не закомментарен?


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: Странник от Апрель 13, 2012, 18:08
в смысле exec отрабатывает без ошибки или видны результаты запроса?
и if 3=3 в коде процедуре не закомментарен?
и exec() отрабатывает, и результаты запроса видны. if 3=3 на месте. более того, в моих проектах на том же MS SQL 2005 в аналогичных случаях никаких проблем не возникало. была трабла с запросами, возвращающими множественный резалтсет, но у вас явно не тот случай.

предлагаю вам собрать демо-проект sqlbrowser и попробовать выполнить через него запрос:
Код:
{CALL teststoreproc (2)}
или
Код:
EXEC teststoreproc 2
если отработает, будем курить ваш код, если нет - нужно копать в сторону ODBC или MS SQL Server.


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: chagovets от Апрель 14, 2012, 11:48
Цитата: Странник
предлагаю вам собрать демо-проект sqlbrowser и попробовать выполнить через него запрос:
Код:
{CALL teststoreproc (2)}
или
Код:
EXEC teststoreproc 2
если отработает, будем курить ваш код, если нет - нужно копать в сторону ODBC или MS SQL Server.

эксперимент произведён :)
результат тот же - при наличии IF'а -  "Forward-only queries cannot be used in a data model"

попытка тут же повторно выполнить exec даёт:

[Microsoft][ODBC SQL Server Driver]Подключение занято до получения результатов для другого hstmt QODBC3: Unable to execute statement


скриншоты прилагаю (http://narod.ru/disk/46059257001.64e168cd43a169ab1b826f55caadae10/jpg.zip.html)

информация о системе (клиент):
Microsoft SQL Server Management Studio      9.00.1399.00
Microsoft Analysis Services Client Tools      2005.090.1399.00
Microsoft Data Access Components (MDAC)   2000.085.1132.00 (xpsp.080413-0852)
Microsoft MSXML                  2.6 3.0 5.0 6.0
Operating System                  5.1.2600

сервер:
Product Microsoft SQL Server Standard Edition
Operating System Microsoft Windows NT 5.2 (3790)
Version 9.00.4262.00

самое интересное - я проверял на MS SQL 2000 в совершенно другой сети  - результат был аналогичный
правда ещё на QSqlTableModel а не на собственной

Цитировать
и exec() отрабатывает, и результаты запроса видны. if 3=3 на месте
ума не приложу - что же  я не так делаю то?...


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: Странник от Апрель 14, 2012, 13:16
прошу прощения, у вас проблема с выполннием запроса или все-таки с моделью? если с моделью, то ответ уже был получен вами ранее: QSqlQueryModel не поддерживает forward-only запросов. isForwardOnly возвращает актуальное состояние резалтсета, а не значение, установленное в setForwardOnly. то есть, MS SQL Server возвращает forward only результат, на чем QSqlQueryModel и затыкается.

почему не работает ваша собственная реализация, давайте разбираться. с ходу вижу, что у вас неверно реализовано добавление данных в модель. не используйте size() или numRowsAffected() для определения числа записей, надежнее крутиться в while(mQuery.next()).


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: chagovets от Апрель 14, 2012, 15:14
Цитировать
проблема с выполннием запроса или все-таки с моделью?
с выполнением запроса из Management Stidio нет ни каких проблем, в любом виде процедура отрабатывает (скриншоты приводил)
как советовали - я из демо sqlbrowser пытался проверять вызов процедуры
о результатах эксперимента с sqlbrowser доложил
само собой, в sqlbrowser используется QSqlQueryModel  - но Вы же утверждаете, что у Вас
Цитировать
и exec() отрабатывает, и результаты запроса видны. if 3=3 на месте.
проверил на MS SQL 2005, драйвера SQL Server и SQL Native Client, Qt 4.8.1.

поскольку
Цитировать
MS SQL Server возвращает forward only результат, на чем QSqlQueryModel и затыкается.
я и решил использовать свою модель
но как оказалось, дело не в forward only результате
о чём выше написал, что проблема осталась

Цитировать
почему не работает ваша собственная реализация, давайте разбираться. с ходу вижу, что у вас неверно реализовано добавление данных в модель. не используйте size() или numRowsAffected() для определения числа записей, надежнее крутиться в while(mQuery.next()).
моя реализация вполне работает
вот только до тех пор пока нет пресловутой "управляющей конструкции" :)
size() я не использую - поскольку MS SQL его не поддерживает - просто код использовался и для других серверов, и закомментарен  сейчас
numRowsAffected() вполне работоспособен на MS SQL - но сейчас я тоже его исключил
ориентируюсь исключительно на next()

НО
как только я раскомментариваю if 3=3 или SET NOCOUNT ON возвращаемый на Qt клиента результат запроса не содержит ни одной записи
вот в чём проблема
и я ни как не могу понять причины этого
сейчас установил MS SQL 2005 Express на рабочую станцию - результат не изменился



Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: Странник от Апрель 15, 2012, 19:49
в самом деле, любопытно. что имеется у меня на MS SQL Express 2005:
- запрос успешно выполняется и при отсутствии, и при наличии управляющих инструкций в хранимой процедуре. результат запроса доступен в QSqlQuery в обоих случаях
- при наличии управляющих инструкций QSqlQuery::isForwardOnly() возвращает true
- numRowsAffected() возвращает -1 (первый затык вашей модели в setQuery), заменяем на while(mQuery.next())
затем ваша модель у меня затыкается на setData (value содержит верные данные из запроса, а index не валиден), дальше пока не копал.
завтра попробую повторить эксперимент на другом сервере, вдруг там запрос не сработает.


Название: Re: MSSQL 2005 Хранимая процедура
Отправлено: chagovets от Апрель 16, 2012, 08:05
Орешек знаний тверд
Но все же, мы не привыкли отступать!


Странник, Вы были правы!
Цитата: Странник
надежнее крутиться в while(mQuery.next()).
я хоть и писал что
Цитировать
numRowsAffected() вполне работоспособен на MS SQL - но сейчас я тоже его исключил
ориентируюсь исключительно на next()
но исключил не до конца
в общем если действительно идти по next() всё встало на свои места
премного благодарен Страннику за наставление на путь истинный ;)

P.S. MS SQL впечатляет в плохом смысле :)