Передача параметров хранимой процедуре

Oleg
Дата: 14.02.2001 12:13:37
Добрый день!
Господа, не поможете ли вы мне с такой проблемой:
Из 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 13:01:19
Если ADO ставилось вместе с MSO2000 то слазь в описание объектов ADO -> ADODB.Recordset
или попробуй всё тоже самое что хотел в VBA в ворде или экселе dim rs as и тд а когда поставишь точку после rs то выдасться список поддерживаемых свойств и методов О!
Всего х...!
Oleg
Дата: 14.02.2001 14:25:47
Спасибо, Дмитрий, за ответ. Но дело не в том, что объект Recordset не поддерживает свойство EOF. Такое сообщение об ошибке говорит, скорее всего о том, что Recordset пуст, а доподлинно известно (и проверено в Query Analizer), что при правильной работе пустым он быть не должен. Здесь, я почти в этом уверен, проблема либо с передачей параметров в хранимую процедуру, либо с возвратом из нее Recordset. Поэтому и привел текст на ASP.
Кроме того, характерно, что вся эта конструкция нормально работала в SQL Server 7.0....
Garya
Дата: 14.02.2001 19:18:38
Несколько странно, что данный код работал с версией 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 не все клиентские продукты совместимы.
Oleg
Дата: 14.02.2001 20:03:01
Garya, спасибо за рекомендации. К сожалению, проставка собак не помогла, к тому же я в книжке тоже видел пример без собак (просто курсы собаководства). Сейчас возникла мысль, что юзеру сайта при переходе с SQL Server 7.0 на SQL Server 2000 не перенесли пермиссии. Сейчас пермиссию на выполнение хранимых процедур прописали, и большинство процедур на сайте заработало, но в этой используется создание временных таблиц, на что, вроде, нужна отдельная пермиссия. Отсюда мой следующий вопрос: может ли быть здесь дело в пермиссиях и, если да, то как прописать разрешение на создание временных таблиц?
qu-qu
Дата: 15.02.2001 10:15:34
Пермишенсы на создание временных таблиц никому не требуются, т.к. это есть - внутренние объекты самого сервера и он создает их в специальной временной базе, в которую допускает любой контекст пользователя (тем более, что существуют эти таблицы только на время исполнения запроса, или процедуры, и только в сессии определенного пользователя, поэтому никого не колышут права на их создание/удаление).

Теперь насчет 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-а, пусть даже в нем пусто как в степи зимой... )
Oleg
Дата: 15.02.2001 11:02:00
qu-qu, Вы попали в самую точку. Теперь разобраться бы с этими директивами в начале процедуры! У нас нет NOCOUNT, зато есть

SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

Может они тоже вред какой наносят? Я чесно не силен в директивах, поэтому опасаюсь особо экспериментировать...
Может надо поставить SET NOCOUNT OFF? А что это будет значить?

И спасибо большое за очень ценный ответ!

З.Ы. Какие уж там банальности? Для меня это просто "высшая математика"!
qu-qu
Дата: 15.02.2001 12:05:42
Ну, с директивами-то "разбираться" - дело как раз нехитрое... (если вы хоть кое-как читаете по-английски).

Обычно вместе с сервером народ проставляет себе 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 и временных таблицах в процедуре) уже обсуждался на форуме у А. Гладченко, который "прирос" к этому форуму... (надо было просто покопаться в архивах).
qu-qu
Дата: 15.02.2001 12:15:51
О, блин, чуть не забыл предупредить (как раз из серии того, что приходит "с опытом").

Некоторые директивы SET уже являются "предустановленными" для любой базы данных (проверяются системной процедурой "sp_dboption"), и самое подлое в этом деле, что некоторые могут быть изменены в пользовательской процедуре, а некоторые - хрена лысого, т.е. если на всю базу установлено более сильное ограничение (например: SET ANSI_WARNINGS ON), то хоть обвставляйся директивами SET ARITHIGNORE ON/OFF - никакого эффекта не последует...

Но, к счастью, обо всех этих "тонких взаимоотношениях" всегда прописано в Books Online.

Удачи!!
SergSuper
Дата: 15.02.2001 12:55:22
2 Oleg
SET NOCOUNT ON НАДО поставить в начало процедуры, а SET NOCOUNT OFF поставить перед последним селектом, который будет выплевывать данные