Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Qt и MSSQL 2005 / 25 сообщений из 35, страница 1 из 2
12.03.2012, 20:40
    #37701571
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
MSSQL 2005, Qt 4.8, QODBC
Имеется хранимая процедура простого содержания:

Код: sql
1.
select field1,field2 from SomeTable



Отрабатывает без проблем.
Изменяю текст процедуры на:

Код: sql
1.
2.
if 3=3
	select field1,field2 from SomeTable




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

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


При этом другой клиент (не Qt) через ODBC в обоих случаях результат получает.
В чём может быть проблема?
...
Рейтинг: 0 / 0
12.03.2012, 21:20
    #37701605
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
Проблема где-то в округе...
Показывай полностью текст процедуры и как ты ее вызываешь с клиента.
...
Рейтинг: 0 / 0
13.03.2012, 10:50
    #37702105
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
таблица:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE TABLE [dbo].[SomeTable](
	[field1] [uniqueidentifier] NOT NULL DEFAULT (newid()),
	[field2] [varchar](50) COLLATE Cyrillic_General_CI_AS NOT NULL DEFAULT ('')
	
) ON [PRIMARY]

insert into SomeTable (field2) values ('test1')
insert into SomeTable (field2) values ('test2')
insert into SomeTable (field2) values ('test3')



код процедуры:
Код: sql
1.
2.
3.
4.
5.
6.
CREATE PROCEDURE [dbo].[teststorproc]
AS
BEGIN
if 3=3
	select * from SomeTable
END



код клиента:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
#include <QtCore>
#include <QtGui>
#include <QtSql>


int main(int argc, char *argv[])
{
    QTextCodec *codec = QTextCodec::codecForName("cp1251");
    QTextCodec::setCodecForTr(codec);

    QApplication app(argc, argv);

    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");

    QString connString;
    connString="DRIVER={SQL Server};" ;
    connString=connString+"Server=servername;" ;
    connString=connString+"Database=dbname;" ;
    connString=connString+"Uid=user;Pwd=pass;";
    db.setDatabaseName(connString);

    if (db.open())
           QMessageBox::information(0,QObject::tr("Информация"),
                                    QObject::tr("Соединение установлено !"));
        else
            {
                QMessageBox::critical(0,
                                  QObject::tr("Ошибка"),
                                  QObject::tr("Не удалось подключиться к базе данных!\n")+
                                      QObject::tr("Ошибка :")+db.lastError().text()
                                  );
                 return 0;
            }

    QSqlQuery *mainQuery;
    QSqlQueryModel *viewModel;

    mainQuery = new QSqlQuery;
    viewModel = new QSqlQueryModel;

    QString sqlString;
    sqlString = "exec teststorproc";

    mainQuery->prepare(sqlString);
    mainQuery->setForwardOnly(true);
    mainQuery->exec();
    if (mainQuery->lastError().isValid())
        {
            QMessageBox::critical(0,
                              QObject::tr("Ошибка"),
                              QObject::tr("Ошибка запроса!\n")+
                                  QObject::tr("Ошибка :")+mainQuery->lastError().text()
                              );
            return 0;
        }
    viewModel->setQuery(*mainQuery);

    while (viewModel->canFetchMore())
        viewModel->fetchMore();

    QTableView *tblView;
    tblView = new QTableView;
    tblView->setSelectionMode(QAbstractItemView::SingleSelection);
    tblView->setModel(viewModel);
    tblView->show();

    return app.exec();
}
...
Рейтинг: 0 / 0
13.03.2012, 10:54
    #37702113
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
> При этом другой клиент (не Qt) через ODBC в обоих случаях результат получает.
> В чём может быть проблема?


Поставь в процедуре в самом начале тела

set nocount on

ОБЯЗАТЛЬЕНО СООБЩИ РЕЗУЛЬТАТЫ !
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2012, 11:00
    #37702125
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
MasterZivset nocount on

это я пробовал с самого начала...
правда не придал значения - но результат тот же
т.е. даже если нет if'а а стоит SET NOCOUNT ON - на клиенте результата нет
...
Рейтинг: 0 / 0
13.03.2012, 11:03
    #37702135
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
> это я пробовал с самого начала...
> правда не придал значения - но результат тот же
> т.е. даже если нет if'а а стоит SET NOCOUNT ON - на клиенте результата нет

???
Чего ?
Не должно такого быть.

Т.е. процедура, в ней --- голый SELECT 42 as val, скажем,
и возвращается набор, а если поставить перед этим
SET NOCOUNT ON

-- не возвращается ?

Проверь, пожалуйста.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2012, 11:10
    #37702158
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
MasterZiv
???
Чего ?
Не должно такого быть.

Т.е. процедура, в ней --- голый SELECT 42 as val, скажем,
и возвращается набор, а если поставить перед этим
SET NOCOUNT ON

-- не возвращается ?

именно так!
сегодня третий день с этим бьюсь :)
менял клиента - с VFP всё гуд
менял станцию клиента - Qt результат отрицательный
менял сервер - Qt результат отрицательный
удивлён не меньше...
до этого из под Qt с MSSQL не работал...
...
Рейтинг: 0 / 0
13.03.2012, 11:13
    #37702163
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
On 03/13/2012 11:50 AM, chagoserg wrote:

Несколько замечаний. Они могут повлиять, а могут и не повлиять на результат, но
всё равно надо так сделать.


sqlString = "exec teststorproc";

Это у тебя -- языковой запрос, его использовать бессмысленно.
Тебе лучше оформить вызов процедуры через RPC.
На ODBC это будет типа

sqlString = "{call teststorproc()}"; // не помню, нужны ли ()

при наличии параметров
sqlString = "{call teststorproc(?,?,?)}";

Также, если в QT выделено как-то общение с хранимыми процедурами отдельно,
типа класс не QQuery, а QProcedure, то лучше использовать этот класс (.
QProcedure).

> mainQuery->prepare(sqlString);

При вызове процедуры НЕ НАДО делать подготовленое выполнение,
не надо делать prepare. Разве что это -- какой-то вызов QT API , без
которого нельзя, в таком случае нужно убедится, что он делает
внутри, не делает ли вызов SQLPrepare (или как его там).

Внутри prepare создаёт из твоего запроса хранимую процедуру, которая у тебя
будет звать другую процедуру. Когда она уже у тебя есть, делать это бесссмысленно.

> mainQuery->setForwardOnly(true);

Если всё сделать так, как я говорю, то setForwardOnly(true); ставить не нужно,
оно и так будет само.

> mainQuery->exec();

В некоторых API различают выполнения запроса и открытие.
типа exec и open . exec -- для тех, которые не возвращают наборы данных,
open -- кто возвращает. Проверь, может ты неверный вызов испльзульешь.


Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2012, 11:28
    #37702219
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
MasterZivНесколько замечаний.
sqlString = "{call teststorproc}";

при наличии параметров
sqlString = "{call teststorproc(?,?,?)}";

всё это я пробовал...
результат одинаковый

MasterZiv mainQuery->prepare(sqlString);

prepare используется если биндятся параметры
это я тоже всё пробовал
наличие prepare на самом деле ни как не влияет на исполнение, разве что на скорость исполнения

MasterZivЕсли всё сделать так, как я говорю, то setForwardOnly(true); ставить не нужно,
оно и так будет само.


Qt Assistent:
ODBC Stored Procedure Support

With Microsoft SQL Server the result set returned by a stored procedure that uses the return statement, or returns multiple result sets, will be accessible only if you set the query's forward only mode to forward using QSqlQuery::setForwardOnly().

Код: plaintext
1.
2.
3.
4.
5.
// STORED_PROC uses the return statement or returns multiple result sets
 QSqlQuery query;
 query.setForwardOnly(true);
 query.exec("{call STORED_PROC}");
>      mainQuery->exec();


собственно пробовал и без setForwardOnly(true)...
MasterZivПроверь, может ты неверный вызов испльзульешь.

я тоже предполагаю что косяк в чём то элементарном ;)
не может же быть такого
тему завёл уже отчаявшись - ни одного писка в тырнете :)
...
Рейтинг: 0 / 0
13.03.2012, 11:54
    #37702299
fte
fte
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
см. хелп по QSqlQuery

Binding values to a stored procedure:

This code calls a stored procedure called AsciiToInt(), passing it a character through its in parameter, and taking its result in the out parameter.

Код: plaintext
1.
2.
3.
4.
5.
6.
     QSqlQuery query;
     query.prepare("CALL AsciiToInt(?, ?)");
     query.bindValue(0, "A");
     query.bindValue(1, 0, QSql::Out);
     query.exec();
     int i = query.boundValue(1).toInt(); // i is 65


Note that unbound parameters will retain their values.

Stored procedures that uses the return statement to return values, or return multiple result sets, are not fully supported. For specific details see SQL Database Drivers.
...
Рейтинг: 0 / 0
13.03.2012, 12:00
    #37702320
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
fteсм. хелп по QSqlQuery
...

ну так и что я пропустил то? :)
в этом примере идёт речь о возврате параметра из ХП
...
Рейтинг: 0 / 0
13.03.2012, 13:20
    #37702546
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
> всё это я пробовал...
> результат одинаковый
>

Это не надо пробовать, это надо так делать.
Оно может и не влиять на желаемый тобой результат,
но так надо делать по уму. Просто потому что надо.


> With Microsoft SQL Server the result set returned by a stored procedure that
> uses the return statement, or returns multiple result sets, will be accessible
> only if you set the query's forward only mode to forward using
> QSqlQuery::setForwardOnly().

Ну ладно, оставь.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2012, 13:34
    #37702576
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
MasterZivЭто не надо пробовать, это надо так делать.
Оно может и не влиять на желаемый тобой результат,
но так надо делать по уму. Просто потому что надо.

скажем так - изначально так и было ;)
через call
я знаю что "надо так" ;)

Для подтверждения заменил:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
    QString sqlString;
    sqlString = "{CALL teststorproc (?)}";
    mainQuery->prepare(sqlString);
    mainQuery->bindValue(0,"2");

    mainQuery->setForwardOnly(true);
    mainQuery->exec();



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE PROCEDURE [dbo].[teststorproc]
@param varchar(10)
AS
BEGIN
--	SET NOCOUNT ON

--if 3=3
select * from SomeTable
where field2 like('%'+ltrim(rtrim(@param))+'%')
END



пока не раскоменнтишь любую из строк всё работает...
...
Рейтинг: 0 / 0
13.03.2012, 14:20
    #37702703
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
>
> CREATE PROCEDURE [dbo].[teststorproc]
> @paramvarchar(10)
> AS
> BEGIN
> -- SET NOCOUNT ON
>
> --if 3=3
> select * from SomeTable
> where field2like('%'+ltrim(rtrim(@param))+'%')
> END

> пока не раскоменнтишь любую из строк всё работает...

Не может быть, чтобы в QT было всё так плохо...



SET NOCOUNT ON короче надо как-то поставить
в той же коннекции до выполнения запроса.

Можно через ODBC API включить его в коннекции (см. документацию на драйвер, по
идее должно поддерживаться), или просто перед этим запросом выполнить
языковой запрос
"SET NOCOUNT ON"

Если и так не будет работать, я уж и не знаю....
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2012, 14:42
    #37702767
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
MasterZivНе может быть, чтобы в QT было всё так плохо...

как бы плохо только с MSSQL :)
точнее с QODBC
и то - по неподтверждённым другими пока данным
может кто-нибудь опровергнет всё же?

MasterZivSET NOCOUNT ON короче надо как-то поставить
в той же коннекции до выполнения запроса.
...
Если и так не будет работать, я уж и не знаю....


не срабатывает...
...
Рейтинг: 0 / 0
13.03.2012, 15:06
    #37702843
fte
fte
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
а на консоли приложения не выводится никакой диагностики?
сдаётся мне, что mainQuery->record() не может правильно сформировать.....

ИМХО:
если Ваша процедура с комментариями, то она трансформируется к виду
create procedure ....
as select ....
выходные параметры процедуры на автомате будут в системных таблицах прописаны, и поэтому вы видите результат,
а если так -
create procedure .....
begin
.....
select a,b,c
select f,d
.....
end
что возвратит Ваша процедура?
a,b,c
f,d,null

думаю
recordset(a,b,c)
recordset(f,d)

а вот это думаю драйвер ODBC не может понять.....
поэтому надо выходные параметры явно указать....
...
Рейтинг: 0 / 0
13.03.2012, 15:57
    #37703014
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
fteа на консоли приложения не выводится никакой диагностики?
сдаётся мне, что mainQuery->record() не может правильно сформировать.....
...
что возвратит Ваша процедура?
a,b,c
f,d,null

думаю
recordset(a,b,c)
recordset(f,d)

если честно - ни чего не понял :)
текст процедуры я выше приводил
fteпоэтому надо выходные параметры явно указать....
там результат запроса - таблица
ни каких выходных параметров нет
результат возвращается при отсутствии дополнительных управляющих конструкций
кстати, проверил на MSSQL2000 - результат идентичный
...
Рейтинг: 0 / 0
13.03.2012, 16:52
    #37703165
fte
fte
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
тогда может так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE FUNCTION [ owner_name. ] function_name 
    ( [ { @parameter_name [AS] scalar_parameter_data_type [ = default ] } [ ,...n ] ] ) 

RETURNS TABLE 

[ WITH < function_option > [ [,] ...n ] ] 

[ AS ] 

RETURN [ ( ] select-stmt [ ) ] 



mainQuery->prepare("select * from dbo.myfunc(2)");
...
Рейтинг: 0 / 0
13.03.2012, 17:27
    #37703289
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
> CREATE FUNCTION [ owner_name. ] function_name
> ( [ { @parameter_name[AS] scalar_parameter_data_type[ =default ] } [ ,...n] ] )
>
> RETURNS TABLE

Не нужно это.
Это нужно, когда результат выполнения процедуры участвует в запросе вместо таблицы.

А чтобы получить данные на клиенте это ни на фиг не нужно.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.03.2012, 20:22
    #37703617
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
проверил QODBC в работе с ASA 8.02 с аналогичной процедурой - всё отлично отрабатывает...
...
Рейтинг: 0 / 0
16.03.2012, 18:21
    #37709001
v6y
v6y
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
chagoserg,
Если всё еще актуально:

В вашем случае

viewModel->lastError() == QSqlError(-1, " Forward-only queries cannot be used in a data model ", "")

Проблема с QSqlQueryModel, а не с драйвером
...
Рейтинг: 0 / 0
16.03.2012, 22:21
    #37709303
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
v6y"Forward-only queries cannot be used in a data model"

Проблема с QSqlQueryModel, а не с драйвером

да, это уже я тоже обнаружил...
только непонятно, почему при отключении управляющих конструкций результат перестаёт быть forward-only
при этом setForwardOnly влияния не оказывает

и кроме того - с ASA 8.02 через QODBC в тоже время нет ни каких проблем хоть стоит forward-only хоть нет...

как я писал выше :
With Microsoft SQL Server the result set returned by a stored procedure that uses the return statement, or returns multiple result sets, will be accessible only if you set the query's forward only mode to forward using QSqlQuery::setForwardOnly().

ужасное противоречие, однако :)
чтобы получить результат ХП от MSSQL надо обязательно сделать setForwardOnly(), но стандартная QSqlQueryModel его не примет
что ж, выход один - своя модель...
...
Рейтинг: 0 / 0
13.04.2012, 14:11
    #37752483
chagoserg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
снова подниму тему...

v6yПроблема с QSqlQueryModel, а не с драйвером
выход один - своя модель...

изготовление собственной модели не стало выходом - проблема осталась.
и дело совсем не в forward-only
MS SQL не возвращает результат, точнее numRowsAffected() равен -1 - "cannot be determined"

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

кому интересно - прикладываю проект
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
21.09.2013, 15:53
    #38403517
Koschey
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
chagoserg,

Столкнулся с такой же проблемой. В хранимой процедуре нельзя ничего разместить кроме одного селекта.
Воспользовался советом Fte. Идея с функцией с инструкциями, возвращающая табличные данные. В коде пишу запрос на выборку данных, вместо таблицы указываю функцию. В свою очередь в функции можно расположить код, который мне необходим. Недостаток в том, что пока не знаю как воспользоваться sp_executesql и заставить функцию вернуть её результат.
Есть еще второй вариант, но я его еще не опробовал.
Это работа с методом QSqlQuery::nextResult(). Он рассчитан на запросы возвращающие несколько наборов данных. В нашем случае, очень похоже, что это и происходит, при включении в текст хранимой процедуры дополнительных команд.
...
Рейтинг: 0 / 0
21.09.2013, 16:12
    #38403525
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt и MSSQL 2005
chagoserg,

Проблема в том, что QT будет ожидать в таком случае набор данных, а посколько select под if, набор никогда не придет, и в соединении с бд возникнет ошибка состояния: клиент запрашивает открытие курсора, а курсора на сервере нет.

Эту проблему легко обойти, выдавая даже в случае else пустой набор данных такой, же структуры. При этом набор появится и клиентское приложение будет довольно.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Qt и MSSQL 2005 / 25 сообщений из 35, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]