Текущий архив: 2004.12.05;
Скачать: CL | DM;
ВнизПроблемы с ADO и multiple recordsets Найти похожие ветки
← →
Тимохов © (2004-10-31 15:50) [0]Добрый день.
(Сервер MSSQL server)
Симптомы проблемы
--------------------
Иногда один и тот же запрос возвращает два recordset вместо одного. Причем, второй recordset является требуемым рекордсетом, а первый - закрытый recordset без единого поля.
Подробное описание
--------------------
Имеется (упрощенно, но суть вопроса отражает точно):
1. Процедура SomeProc с параметром Param1, которая возвращает ровно один Recordset.
2. Некий клиентский запрос, который:
а) Выполняет SomeProc
б) Полученный рекордсет возвращает как результат предварительно сбросив его во временную таблицу и несколько обработав.
схематически код выглядит так:
create #t (fld1 int, fld2 int)
insert #t (fld1, fld2) exec SomeProc Param1
insert SomeTable select distinct fld1, fld2 from #t
select fld1, fld2 from #t
который я выполняю с использованием AdoDb.Command (связываение раннее). Например такCmd := ADODB.CoCommand.Create;
Cmd.Set_CommandText(<текст приведенного выше запроса>); Cmd.Set_CommandType(adCmdText);
Cmd.Set_CommandTimeout(1000);
Cmd.Set_ActiveConnection(Cnn);
RS := Cmd.Execute(kRecordsAffected, VarArrayOf([...параметры...]), adCmdUnspecified);
При этом по непонятному закону при одном и том же значении параметров иногда оказывается, что RS = пустому закрытому recordset и для того, чтобы получить нужный нужно вызывать RS.NextRecordSet. Природу первого рекорсета я понять не могу. Ниже я объясню, как пытался понять.
Что я делал для того, чтобы решить проблему
---------------------------------------------
1) Сразу возникло подозрение, что в SomeProc (ее писал не я) есть два Select или Compute (согласно MSDN именно эти конструкции генерят несколько recordset). Но при детальном анализе PROFILER"а в режиме просмотра абсолютно всех интструкций (в том числе и внутри процедур) и кода процедры видно, что никакого лишнего select и compute нет.
2) Одно из решений проблемы было такое - взять тело процедуры и полность перенести в скрипт. В этом случае все работает ОК.
3) Всю документацию, которая доступна я уже просмотрел. Везде пишут как делать несколько recordset, но откуда может браться лишний никто не пишет.
4) Накатил mdac 2.8 - ничего не изменилось.
Что я думаю по этому поводу
-----------------------------
У меня есть устойчивое ощущение, что это есть глюк. Глюк ado или сервера в конструкции insert ... exec ...
При том, что ado и sql server"ом я занимаюсь пятый год и свое время прочел все что можно, куда копать я не знаю.
Вопрос
-------
1) Встречался ли кто-нибудь с таким поведением ado при использовании insert ... exec ...?
2) Если это все-же тянет на глюк, то где в msdn читать о заявленных ошибках (если я не ошибаюсь это должно быть)?
Заранее благодарен.
← →
sniknik © (2004-10-31 17:26) [1]из приведенного запроса вернется 4 рекордсета(с установками по дефаулту) только последний с данными, первые пустые только с количеством применненных записей.
если пустые не нужны первой должна быть команда SET NOCOUNT ON
кстати твой непонятный закон как раз может быть тем что с этой командой безалаберно обращаются ;о) (гдето в другом месте до твоего включают/отключают), и у тебя все зависит после чего это вызвано.
← →
Тимохов © (2004-10-31 17:40) [2]
> [1] sniknik © (31.10.04 17:26)
Ну началось... :)
Почти месяц не было меня на форуме, подзабыл дух издевки:)))
По делу.
> если пустые не нужны первой должна быть команда SET NOCOUNT ON
Это не оказывает влияния :)) Пробовал уже.
Я попробовал 342 варианта решения (из нормальных). Кто больше?
Повторю, что решение с заменой inset ... exec на insert ... select с выносом кода процедуры в мой запрос (и, конечно, удалением процедуры) работает правильно.
← →
sniknik © (2004-10-31 17:51) [3]где издевка? вполне серьезно.
> Это не оказывает влияния :)) Пробовал уже.
а в процедуре твоей смотрел? может там вызывается с OFF.
> Повторю, что решение с заменой inset ... exec на insert ... select с выносом кода процедуры в мой запрос (и, конечно, удалением процедуры)
> работает правильно.
ну вот почти подтвердил.
можно обойти, цикл с NextRecordSet организовать, до последнего рекордсета (вернее предпоследнего ;о) последний будет nil), тоже пробовал судя по описанию?
← →
Тимохов © (2004-10-31 17:57) [4]
> [3] sniknik © (31.10.04 17:51)
Ты читал в после про исползование profiler"a?
Конечно я смотрел и код процедуры и резуьтат работы profiler - я смотрел каждый statment в том числе и внутри процедуры. Заметь, что ошибка происходит не всегда. Один и тот же запрос, то выполнятеся, то нет. Вероятность примерно 1 к 1.
> можно обойти, цикл с NextRecordSet организовать, до последнего
> рекордсета (вернее предпоследнего ;о) последний будет nil),
> тоже пробовал судя по описанию?
И хто я после этого - чмо-ламо? Пока мне ничего не остается, как сделать именно так.
← →
Тимохов © (2004-10-31 18:10) [5]
> [3] sniknik © (31.10.04 17:51)
Проблема состоит именно в том, что решение насущной проблемы я знаю. Но почему получается так?
Не скрою, что у нас (уж извините) просто изнасилованный сервер. Он делает большую долю несвойственной sql серверам работу. Например, он является mapper"ом между объектной моделью в дельфи и реляционными таблицами в себе же. Изначально все это позиционировалось как реляционная надстройка над реляционной базой. В принципе в настоящий момент все именно так и работает - полиформизм и наследование исползуются достаточно активно. В принципе и инкапсуляция есть, но пока не полная.
Но не редки случае, когда некие компоненты сервера (оптимизатор, например) от запросов приходят в ступор. Запрос разбирается 3 минуты, а выполяется 388 мс. Но в таких случая глубокого знания поведения сервера (я имею в виду наших админов) хватает, чтобы с помощью хинтов направить поведение сервера в правильное русло. Часто наши запросы проигрывают чистой реляционке совсем немного.
Но в данном случае, все разводят руками...
Вот и интересуем меня, может у кого-то тоже запученный до потери сознания сервер, который приводит к таким вот глюкам.
← →
sniknik © (2004-10-31 18:30) [6]ну не знаю, проверил у себя, никаких неожиданностей
сначала сделал простую процедуруCREATE PROCEDURE SomeProc @Param1 integer
AS
SELECT ID, CurrencyID
FROM CurrencyRate
WHERE CurrencyID=@Param1
после выполняю твой блок (исправил небольшой глюк, описался? прям сдесь писал?)
create table #t (fld1 int, fld2 int)
insert #t (fld1, fld2) exec SomeProc 1
insert SomeTable select distinct fld1, fld2 from #t
select fld1, fld2 from #t
drop table #t
получаю
Выполнено применительно к 1 записям. (no recordset)
применительно к 1 записям. (no recordset)
применительно к 1 записям
ничего наожиданного, да?
потом заменил процедуру наCREATE PROCEDURE SomeProc @Param1 integer
AS
IF @Param1 = 1 SET NOCOUNT ON
ELSE SET NOCOUNT OFF
SELECT ID, CurrencyID
FROM CurrencyRate
WHERE CurrencyID=@Param1
ну так, для проверки
и с еденицей и с двойкой в параметре все одно несколько записей
Выполнено применительно к 6 записям. (no recordset)
применительно к 6 записям. (no recordset)
применительно к 6 записям
... от NOCOUNT внутри процедуры независит (ошибся я), а вот в начале блока очень даже зависит.
проверь также, на упрощенных данных может что прояснит.
← →
Johnmen © (2004-11-01 09:15) [7]>Тимохов © (31.10.04 17:40) [2]
>Ну началось... :)
>Почти месяц не было меня на форуме, подзабыл дух издевки:)))
И что ты делал этот месяц, что стал таким нервным и раздражительным ? Может стОит поспокойнее ?
← →
Тимохов © (2004-11-01 11:25) [8]
> [7] Johnmen © (01.11.04 09:15)
Смайлики видел? :)))
> [6] sniknik © (31.10.04 18:30)
Если ошибку не найду пришлю неработающий пример. Пока с примером проблемы. Составляю его удалением лишнего из нашего сервера. Муторная это работа.
← →
Тимохов © (2004-11-01 11:27) [9]
> [7] Johnmen © (01.11.04 09:15)
Смайлики видел? :)))
> [6] sniknik © (31.10.04 18:30)
Если ошибку не найду пришлю неработающий пример. Пока с примером проблемы. Составляю его удалением лишнего из нашего сервера. Муторная это работа.
> после выполняю твой блок (исправил небольшой глюк, описался?
> прям сдесь писал?)
Я же сказал, что пример упрошенный, конечно тут писал.
← →
Тимохов © (2004-11-01 11:42) [10]
> [7] Johnmen © (01.11.04 09:15)
Еще раз повторю дабы не тратить время на раздумия - set nocount on!!!
Дошел до маразма - ставил его перед каждой строкой своего скрипта и каждой строкой процедуры :)))
Нету такому поведению нормального объяснения.
А я сошла с ума (с) Фрейкин бок.
← →
Суслик © (2004-11-04 12:36) [11]Up.
Может у кого появятся идеи... а может нет :(
Страницы: 1 вся ветка
Текущий архив: 2004.12.05;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.037 c