|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Добрый день! Господа, не поможете ли вы мне с такой проблемой: Из ASP через ADO вызывается хранимая процедура в SQL Server 2000: Set cmd=Server.CreateObject("ADODB.Command") cmd.CommandText="int_ReturnTable" cmd.CommandType=adCmdStoredProc cmd.ActiveConnection=Main1 cmd.Parameters.Append cmd.CreateParameter("EquipNo", adInteger, adParamInput, 4, 1) cmd.Parameters.Append cmd.CreateParameter("Buget", adVarChar, adParamInput, 25, "100000") Set RS = Server.CreateObject ("ADODB.Recordset") RS=cmd.Execute Эта конструкция нормально работала с SQL Server 7.0. При вызове этой процедуры из QA в SQL Server 2000 все тоже работает и выдает правильный непустой рекордсет. Однако в ASP рекордсет видимо не создается, поскольку при следующей записи Do While Not RS.EOF пишется, что не знает у объекта такого свойства EOF. С соединением Main1 все в порядке, так как другие процедуры под ним работают. Помогите, пожалуйста! ... |
|||
:
Нравится:
Не нравится:
|
|||
14.02.2001, 12:13 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Если ADO ставилось вместе с MSO2000 то слазь в описание объектов ADO -> ADODB.Recordset или попробуй всё тоже самое что хотел в VBA в ворде или экселе dim rs as и тд а когда поставишь точку после rs то выдасться список поддерживаемых свойств и методов О! Всего х...! ... |
|||
:
Нравится:
Не нравится:
|
|||
14.02.2001, 13:01 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Спасибо, Дмитрий, за ответ. Но дело не в том, что объект Recordset не поддерживает свойство EOF. Такое сообщение об ошибке говорит, скорее всего о том, что Recordset пуст, а доподлинно известно (и проверено в Query Analizer), что при правильной работе пустым он быть не должен. Здесь, я почти в этом уверен, проблема либо с передачей параметров в хранимую процедуру, либо с возвратом из нее Recordset. Поэтому и привел текст на ASP. Кроме того, характерно, что вся эта конструкция нормально работала в SQL Server 7.0.... ... |
|||
:
Нравится:
Не нравится:
|
|||
14.02.2001, 14:25 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Несколько странно, что данный код работал с версией 7.0, поскольку и с ней он работать не должен. Если Command имеет тип adCmdCtoredProc, то имя параметров должно задаваться в точности такими, как они заданы в объявлении хранимой процедуры, включая собаку: cmd.Parameters.Append cmd.CreateParameter("@EquipNo", adInteger, adParamInput, 4, 1) cmd.Parameters.Append cmd.CreateParameter("@Buget", adVarChar, adParamInput, 25, "100000") Это во-первых. Во-вторых, ты ничего не сказал о том, какой версии MDAC используешь. Я не пробовал работать из-под VB6 с MS SQL-2000, но русский MS Access-2000 с ним несовместим (для английского недавно вышел патч, устраняющий эту несовместимость). С MS SQL-2000 работать можно только с MDAC 2.6 (или выше). Однако с MDAC 2.6 не все клиентские продукты совместимы. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.02.2001, 19:18 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Garya, спасибо за рекомендации. К сожалению, проставка собак не помогла, к тому же я в книжке тоже видел пример без собак (просто курсы собаководства). Сейчас возникла мысль, что юзеру сайта при переходе с SQL Server 7.0 на SQL Server 2000 не перенесли пермиссии. Сейчас пермиссию на выполнение хранимых процедур прописали, и большинство процедур на сайте заработало, но в этой используется создание временных таблиц, на что, вроде, нужна отдельная пермиссия. Отсюда мой следующий вопрос: может ли быть здесь дело в пермиссиях и, если да, то как прописать разрешение на создание временных таблиц? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.02.2001, 20:03 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Пермишенсы на создание временных таблиц никому не требуются, т.к. это есть - внутренние объекты самого сервера и он создает их в специальной временной базе, в которую допускает любой контекст пользователя (тем более, что существуют эти таблицы только на время исполнения запроса, или процедуры, и только в сессии определенного пользователя, поэтому никого не колышут права на их создание/удаление). Теперь насчет ADO и вызова процедур с временными таблицами: может я и не в ту сторону киваю, но даже на MS SQL 7.0 при открытии рекордсета в ADO путем банального Set recordset = command.Execute( "my_proc @my_param1=0, @my_param2=null" ) наблюдались довольно странные вещи... А именно: - если в процедуре не было использования временных таблиц, то recordset нормально открывался и был пустым даже если итоговый запрос в вызываемой процедуре не возвращал НИ ЕДИНОЙ строчки... Просто свойство EOF у этого recordset-а честно было равно True; - если же в процедуре использовались временные таблицы, то (при определенных условиях) recordset ни за что не хотел открываться (и соотв-но свойства EOF у него НЕ БЫЛО), хотя он заведомо не должен был быть пустым, т.к. вызов той же процедуры с теми же параметрами в QA давал замечательную выборку данных... Что же это за "определенные условия"? Как ни странно, это инструкция SET NOCOUNT ON в самом начале любой процедуры, которая использует временные таблицы (вам, наверное, приходилось наблюдать в окне QA очень "информативные" сообщения типа "(n row(s) affected)" на каждое действие с временной таблицей в ходе выполнения процедуры, вот они-то как раз и не нужны никому нафиг при открытии рекордсета, человек-то может "абстрагироваться" от этого мусора при просмотре результатов, а вот ADO не может). Может, я пишу и банальности, которые всем известны, но мне самому пришлось довольно долго с этим протрахаться, да еще и понаблюдать как с этим трахались пара моих знакомых... З.Ы. А для проверки открытия recordset-а (ИМХО) лучше сначала использовать свойство State и проверять его на равенство adStateOpen, т.к. EOF действительно существует ТОЛЬКО у открытого recordset-а, пусть даже в нем пусто как в степи зимой... ) ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 10:15 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
qu-qu, Вы попали в самую точку. Теперь разобраться бы с этими директивами в начале процедуры! У нас нет NOCOUNT, зато есть SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO Может они тоже вред какой наносят? Я чесно не силен в директивах, поэтому опасаюсь особо экспериментировать... Может надо поставить SET NOCOUNT OFF? А что это будет значить? И спасибо большое за очень ценный ответ! З.Ы. Какие уж там банальности? Для меня это просто "высшая математика"! ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 11:02 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Ну, с директивами-то "разбираться" - дело как раз нехитрое... (если вы хоть кое-как читаете по-английски). Обычно вместе с сервером народ проставляет себе Books Online, где все достаточно подробно написано (жаль, что по-английски). Для более-менее "адекватного" понимания текстов из Books Online (ИМХО) нужно немного иметь представления об "архитектуре" функционирования SQL-серверов вообще (к сожалению, это приходит только с опытом), а в Books Online узнавать только "частности" для конкретной версии MS SQL Server. Если вы действительно хотите "разобраться" и при этом не напрягать пользователей изменениями в рабочих процедурах - напишите ЛЮБУЮ "тестовую" процедуру лично для себя и ставьте туда ЛЮБЫЕ директивы SET, т.к. их действие ограничено только вашим коннектом и временем исполнения этой процедуры. Что же касается конкретики: SET QUOTED_IDENTIFIER OFF - выключает режим распознавания имен объектов, записанных в двойных кавычках (например так: SELECT "my_field" FROM "My_Table" при данной установке не прокатит, хотя по стандарту ANSI допустимо), полезность данной установки в том, что можно строковые переменные заключать в двойные кавычки, если есть необходимость засунуть туда апострофы (например так: EXEC("select * from my_table where my_text_field like '%BullShit%' and my_flag_field is not null")). GO SET ANSI_NULLS ON - включает режим сравнения NULL в стандарте ANSI (SQL-92), т.е. ЛЮБОЕ сравнение значения с NULL будет возвращать False (что "... WHERE my_field<>NULL ...", что "... WHERE my_field=NULL ..." не выберет вам НИ ОДНОЙ СТРОЧКИ независимо от значения поля "my_field", т.е. придется вам использовать более правильную (с точки зрения стандарта ANSI SQL-92) конструкцию "... WHERE my_field is [not] NULL ...", это "дисциплинирует" ) GO SET NOCOUNT OFF - отключает режим, когда строчки (n row(s) affected) НЕ ОТОБРАЖАЮТСЯ, соотв-но - SET NOCOUNT ON включает этот режим. Кстати, GO совершенно необязательно писать за каждой директивой, т.к. контекст их использования все равно ограничен телом процедуры... З.Ы. Спасибо за добрые слова... , а слово "банальный" я использовал только лишь потому, что данный вопрос (об ADO recordset и временных таблицах в процедуре) уже обсуждался на форуме у А. Гладченко, который "прирос" к этому форуму... (надо было просто покопаться в архивах). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 12:05 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
О, блин, чуть не забыл предупредить (как раз из серии того, что приходит "с опытом"). Некоторые директивы SET уже являются "предустановленными" для любой базы данных (проверяются системной процедурой "sp_dboption"), и самое подлое в этом деле, что некоторые могут быть изменены в пользовательской процедуре, а некоторые - хрена лысого, т.е. если на всю базу установлено более сильное ограничение (например: SET ANSI_WARNINGS ON), то хоть обвставляйся директивами SET ARITHIGNORE ON/OFF - никакого эффекта не последует... Но, к счастью, обо всех этих "тонких взаимоотношениях" всегда прописано в Books Online. Удачи!! ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 12:15 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
2 Oleg SET NOCOUNT ON НАДО поставить в начало процедуры, а SET NOCOUNT OFF поставить перед последним селектом, который будет выплевывать данные ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 12:55 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Господа, Спасибо огромное за науку! Я запустил sp_dboption и она, если я правильно понял, выдает список опций, которые можно менять. Так вот NOCOUNT там отсутствует... Это значит, что она где-то выше прописана? И еще, я попробовал в начало процедуры прописать SET NOCOUNT... Так после создания процедуры эта строчка пропадает, и, естественно, никакого эффекта: n rows affected все равно пишется... Подскажите, пожалуйста, что делать? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 15:12 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
>Я запустил sp_dboption и она, если я правильно понял, выдает список опций, которые можно менять. Так вот NOCOUNT там >отсутствует... Это значит, что она где-то выше прописана? Нет, немножко не так... (вот он для чего опыт-то нужен, если этого не знаешь, или кто-то не рассказал - то хрен сам и догадаешься). Все параметры (опции) SET {DIRECTIVE} имеют 2 состояния ("вкл."/"выкл." ON/OFF), соответствующие команды эти опции включают (SET ... ON), или отключают (SET ... OFF), процедура sp_dboption показывает список опций, которые имеют состояние "ON" (т.е. все остальные возможные опции уже установлены в "OFF", как и ваш NOCOUNT, который "отсутствует"). >И еще, я попробовал в начало процедуры прописать SET NOCOUNT... Так после создания процедуры эта строчка пропадает ??!! Вот этого я совсем не понял... , как это - "пропадает"? Т.е. получается, что в тексте процедуры после ее генерации не остается строчки "SET NOCOUNT..."? Приведите здесь (если не сложно) 5-7 строчек из начала процедуры, чтобы было ясно - как оно написано? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 15:40 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Насчет пропадающий NOCOUNT, такой анекдот, думаю намек будет понятен ------------------ Один 80-летний старик пришел к врачу на медосмотр. - Ну, как вы себя чувствуете? - спрашивает его врач. - Лучше, чем когда-либо, - браво отвечает старичок, - у меня 18-летняя подруга, она беременна и скоро родится наш ребенок. Ну, что скажете, доктор? Доктор подумал минутку и говорит: - Я расскажу вам одну историю. Знавал я одного человека, заядлого охотника. Собрался он однажды на охоту и по ошибке вместо винтовки взял с собой зонтик. И вот идет он по лесу, как вдруг откуда ни возьмись вылезает огромный медведь, и прямо на него! Мужик этот не растерялся, вскинул зонтик, нажал на ручку и.... медведь замертво свалился у его ног! - Нуууу, это же невозможно, - возразил старичок,- наверное, кто-то другой в это время выстрелил. - Собственно, - сказал доктор, - к этому я и пытаюсь подвести наш разговор.... ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 15:45 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
)))) прикольный анекдот. С пропадающими директивами такая штука: я потом попробовал вообще директивы SET удалить, т.е. процедура начиналась со слов CREATE PROCEDURE ... Так после создания процедуры там спереди опять стояло SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO То есть, что там в директивах ни прописывай, все одно получается... Вот такой полтергейт! ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 16:05 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
...то есть, полтергейст. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 16:10 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Ну попробуйте вот такую фигнюшку исполнить: if Exists(SELECT * FROM sysobjects WHERE id=object_id('dbo.my_tmp_proc')) drop Procedure dbo.my_tmp_proc GO create procedure my_tmp_proc @pDate datetime = null as begin set nocount on declare @sDate datetime, @iCount int create table #T (tDate datetime) if @pDate is null insert into #T select getdate() else insert into #T select @pDate select @iCount=-1 while @iCount>=-5 begin select @sDate=min(tDate) from #T insert into #T select dateadd(month,-1,@SDate) select @iCount=@iCount-1 end exec('select * from #T') return end GO exec my_tmp_proc GO sp_helptext my_tmp_proc А потом скажете мне - что и куда там пропадает? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 16:30 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
А посредством какого програмного продукта ты процедуры создаешь? (я пытаюсь выяснить кто это другой, кто стрелял ) ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 16:34 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
>А посредством какого програмного продукта ты процедуры создаешь? >(я пытаюсь выяснить кто это другой, кто стрелял) Да уж... вопрос, что называется - "не в бровь, а в глаз"... Я например, видел собственными глазами как в MS SQL 7.0 Enterprise Manager посылал серверу SET-директивы ДИМЕТРАЛЬНО-ПРОТИВОПОЛЖНЫЕ тем, которые посылал Query Analyzer (и все это "в фоне", независимо от желания пользователя)... (т.е. один и тот же текст на T-SQL вызывал разную реакцию, в зависимости от того - каким приложением пытались создавать процедуру). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 17:07 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Посредством Query Analizer... Произошел облом Спасибо qu-qu, я конечно не туда вставлял директивы! Из Вашего примера, понял куда надо. Все нормально проставил, процедура нормально работает, "n rows affected" пишется один раз, но толку мало. Recordset все равно не создается, опять она не знает такого свойства EOF. Вобщем откуда ушли, туда и... ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 17:10 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Не отчаивайся... (жаль, у меня рабочий день заканчивается, завтра мне, наверное, уже лень будет опять "обсасывать" эту тему). Попробуй быть "последовательным"... Не делай так, как советовал SergSuper: "SET NOCOUNT ON НАДО поставить в начало процедуры, а SET NOCOUNT OFF поставить перед последним селектом, который будет выплевывать данные", (я етого никогда не советовал). Не нужны для открытия рекордсета НИКАКИЕ "(n row(s) affected)" (ни 1 раз, ни 0 раз - вообще избавься от них). Т.е. оставь только SET NOCOUNT ON сразу после CREATE PROCEDURE ... AS ... На установки db_options это НИКАК не повлияет, т.к. "жить" оно будет только во время исполнения этой процедуры. ("Еще 1 рывок, еще 1-на попытка!!") ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 17:41 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Не помогло... Вот ведь непонятки какие! Из QA работает, а из ADO - нет. Ну в чем разница то, причем только в SQL Server 2000? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 18:08 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
1. Set nocount on - директива, без которой могут наблюдаться ИНОГДА чудеса (не всегда). Лично я наблюдал их при использовании рекурсивных триггеров. Дабы раз и навсегда устранить подозрения, что в твоих глюках виноват NOCOUNT, установи галочку на свойстве NO COUNT сервера в Enterprice Manager. Исправлять текст процедуры смысла тогда не будет. Только учти, что все запросы из QA перестанут выводить строчку ... rows affected. 2. Собаку в параметрах ставить обязательно при использовании VBA Access-2000 - могу дать на отсечение свою гелевую ручку. Насчет ASP поклясться не могу. В тех скриптах, в которых можно задавать любое имя параметра, используется тип команды adCmdText (а не adCmdStoredProc), а текст команды задается не просто в виде имени хранимой процедуры, а в виде строки вызова хранимой процедуры:"exec MyProc ?, ? out" - вот в таком виде параметры могут именоваться хоть "МамаМылаРаму" - до фени. Число знаков вопроса должно соответсвовать числу параметру, объявленному в SP. Возле параметров, через которые возвращаются значения, должно обязательно стоять OUT. 3. Возможно я повторяюсь, но ты опять ничего не сообщил про версию MDAC. Если ты пытаешься работать через 2.1 или 2.5, то полученный отрицательный результат при работе с MS SQL-2000 вполне закономерен. И еще советую убедиться, что IIS, который ты используешь, нормально работает с MDAC 2.6 (Access-2000 без соответсвующего патча этого делать не может). 4. Если все-таки все предыдущие высказывания не приводят к нашариванию палки, застрявшей в колесе, проверь, не запускаешь ли ты Command в асинхронном режиме. Если это так, то отрицательный результат тоже очевиден. При работе в асинхронном режиме прежде чем пытаться обращаться к свойствам Recordset, нужно дождаться пока Command выполнит команду и вернет результирующий набор записей. А до того крутиться в цикле, проверяя статус (как правильно посоветовали выше). 5. В приведенном тобой коде есть одна странность. CreateObject для recordset выдавать не обязательно. Он сам создается при выполнении метода .Execute объекта Command. Эта строчка просто лишняя. Более того, она может способствовать утечкам памяти. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 19:47 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Да, чуть не забыл... 6. В строчке: cmd.Parameters.Append cmd.CreateParameter("EquipNo", adInteger, adParamInput, 4, 1) там где у тебя стоит четверка, имеет смысл оставить пустоту. ADO само знает, каков размер полей такого типа. Дело в том, что этот Integer при указании типа параметра - это не тип VB, а тип OLEDB. Он может занимать место в памяти вовсе не такое, какое занимает тип Integer в VB. Советую написать так: cmd.Parameters.Append cmd.CreateParameter("EquipNo", adInteger, adParamInput, , 1) Я всегда писал именно так, и все нормально работало. Хотя, мои опасения о различии размеров схожих типов ADO и VB могут оказаться и беспочвенными. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 19:55 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
Garya, прежде всего спасибо. Отвечу тебе также по пунктам: 1. Set nocount on по крайней мере в этой процедуре уже стоит и дело свое делает, остальные меня пока не очень волнуют. 2. adCmdStoredProc на adCmdText исправил. Строку вызова исправил. То же самое... 3. Не сказал сразу версию MDAC, поскольку к своему стыду не знаю, что это такое и даже как расшифровывается. Объясни, пожалуйста, я тогда попробую узнать. 4. Что такое "асинхронный режим" я тоже не очень представляю. Но рекомендацию в жизнь воплотил в виде такого кода: RS=cmd.Execute Do While RS.State <> adStateOpen Loop Пишет, что не знает у объекта такого свойства State. 5. Объявление Recordset закоментировал. Теперь память не утекает, но работать все равно не работает. 6. Четверку из объявления параметров убрал. Результат - тот же... Вобщем, заворачиваюсь в простыню и ползу на кладбище ... |
|||
:
Нравится:
Не нравится:
|
|||
15.02.2001, 20:39 |
|
Передача параметров хранимой процедуре
|
|||
---|---|---|---|
#18+
МУЖИКИ!!! ОНО РАБОТАЕТ!!! ВСЕМ ГРОМАДНОЕ СПАСИБО!!! ОСОБЕННОЕ СПАСИБО Garya, qu-qu, SergSuper!!! ВЫ МНЕ ОЧЕНЬ ПОМОГЛИ!!! Что конкретно сыграло решающую роль уже не очень понятно, но работать начало после посильного воплощения последних рекомендаций Garya. Хотя потом, когда делал по аналогии смежный случай, следовал всем, выданным мне советам. Вобщем, СПАСИБО!!! ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2001, 15:22 |
|
|
start [/forum/topic.php?fid=46&msg=32002306&tid=1827330]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
43ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
58ms |
get tp. blocked users: |
2ms |
others: | 262ms |
total: | 411ms |
0 / 0 |