Привет всем.
Столкнулся со транным поведение MS SQL Server. Что делаю: создаю процедуру, которая возвращает один рекордсет, и открываю его ADODB::Recordset-ом из Visual C++ 6.
Так вот, если процедура имеет такой вид:
CREATE PROCEDURE Temp
AS
SELECT * FROM Users
то всё происзодит нормально.
Если же процедура имеет вид:
CREATE PROCEDURE Temp
AS
SELECT * INTO #t FROM Users
SELECT * FROM #t
DROP TABLE #t
то по какой-то причине получившийся рекордсет имеет первый набор записей пустой, у него rs->State = adStateClosed. После того, как я делаю
rs2=rs->NextRecordSet(NULL), я получаю доступ к данным.
Собственно говоря вопро вот в чём: кто-нибудь с этим встречался? И если да, то мож кто знает, как избежать подобного поведения MS SQL сервера? Буду благодарен за любые предложения.
Здравствуйте Zar, Вы писали:
Zar>Собственно говоря вопро вот в чём: кто-нибудь с этим встречался? И если да, то мож кто знает, как избежать подобного поведения MS SQL сервера? Буду благодарен за любые предложения.
Это известная фича. Ты получешь счетчик обработанных записей с первого селекта в первом рекордсете.
Поставь в начале процедуры: SET NOCOUNT ON
Здравствуйте Lexey, Вы писали:
L>Здравствуйте Zar, Вы писали:
Zar>>Собственно говоря вопро вот в чём: кто-нибудь с этим встречался? И если да, то мож кто знает, как избежать подобного поведения MS SQL сервера? Буду благодарен за любые предложения.
L>Это известная фича. Ты получешь счетчик обработанных записей с первого селекта в первом рекордсете. L>Поставь в начале процедуры: SET NOCOUNT ON
хъ
L>Это известная фича. Ты получешь счетчик обработанных записей с первого селекта в первом рекордсете. L>Поставь в начале процедуры: SET NOCOUNT ON
ИМХО ты не прав. Хранимаю процедура в MS SQL может возвращать несколько рекордсетов за раз. Здесь именно такой случай. Возвращается два рекордсета, однако первый на момент fetch'а указывает на удаленную таблу, поэтому он не может быть открыт. Со вторым все нормально.
Здравствуйте Алекс, Вы писали:
А>Здравствуйте Lexey, Вы писали:
А>хъ
L>>Это известная фича. Ты получешь счетчик обработанных записей с первого селекта в первом рекордсете. L>>Поставь в начале процедуры: SET NOCOUNT ON
А>ИМХО ты не прав. Хранимаю процедура в MS SQL может возвращать несколько рекордсетов за раз. Здесь именно такой случай. Возвращается два рекордсета, однако первый на момент fetch'а указывает на удаленную таблу, поэтому он не может быть открыт. Со вторым все нормально.
Хм... А почему же тогда SET NOCOUNT ON помогает? Если первый рекордсет — действительно удалённая таблица #t, то по идее не должно помагать...
Здравствуйте Алекс, Вы писали:
А>ИМХО ты не прав. Хранимаю процедура в MS SQL может возвращать несколько рекордсетов за раз.
Проверь, если не веришь. Насчет рекордсетов можешь мне не объяснять, это я и так знаю.
>Здесь именно такой случай. Возвращается два рекордсета, однако первый на момент fetch'а указывает на удаленную таблу, поэтому он не может быть открыт. Со вторым все нормально.
Посмотри внимательно на sql-batch.
Первый стейтмент никакого рекордсета не возвращает. Зато он возвращает счетчик вставленных строк.
Второй стейтмент возвращает записи из таблицы. То, что эту таблицу потом грохают, никого не волнует.
Здравствуйте Алекс, Вы писали:
L>>Посмотри внимательно на sql-batch. L>>Первый стейтмент никакого рекордсета не возвращает. Зато он возвращает счетчик вставленных строк.
А>Он возвращает пустой рекордсет.
Ну хватит гнать пургу. Возми QA да посмотри.
А>Почеve тогда обыкновенный
А>
А>create proc aaa as select * from aaa_tbl
А>
А>Возвращает один рекордсет, хотя информация о кол-ве выбранных строк тоже имеется?
Потому что информация о числе строк идет после рекордсета.
Процедура возвратит 2 резалтсета (если не стоит nocount on):
1) собственно рекордсет
2) число выбранных записей.
хъ
L>Потому что информация о числе строк идет после рекордсета.
L>Процедура возвратит 2 резалтсета (если не стоит nocount on): L>1) собственно рекордсет L>2) число выбранных записей.
Второй рекордсет у меня пустой. Можешь объяснить почему? (стоит nocount on):
Здравствуйте Алекс, Вы писали:
L>>Ну хватит гнать пургу. Возми QA да посмотри.
А>Ссылку пожалуйста!
На что, на Query Analyzer тебе ссылку дать?
L>>Потому что информация о числе строк идет после рекордсета.
L>>Процедура возвратит 2 резалтсета (если не стоит nocount on): L>>1) собственно рекордсет L>>2) число выбранных записей.
А>Второй рекордсет у меня пустой. Можешь объяснить почему? (стоит nocount on):
С nocount on второго рекодсета нет вообще.
А>З.Ы. Не нервничай и не оверквоть!
As long as there are additional results and the Recordset containing the compound statements is not disconnected or marshaled across process boundaries, the NextRecordset method will continue to return Recordset objects. If a row-returning command executes successfully but returns no records, the returned Recordset object will be open but empty. Test for this case by verifying that the BOF and EOF properties are both True. If a non–row-returning command executes successfully, the returned Recordset object will be closed, which you can verify by testing the State property on the Recordset. When there are no more results, recordset will be set to Nothing.
Счетчик как раз попадает в категорию non-row resultset.
А>Давай еще раз. Ты утверждаешь А> А>Процедура возвратит 2 резалтсета (если не стоит nocount on): А>1) собственно рекордсет А>2) число выбранных записей. А>
Да. И это так и есть.
А>Второй рекордсет у меня пустой. Т.е. его вообще нет. Nothing есть такое понятие в VB. Почему?
Пустой и вообще нет — совершенно разные вещи. Пустой — это BOF = EOF = TRUE.
А>Код следующий
А>
А>ALTER proc aa_proc as
А>set nocount off
А>select * from fff
А>
У меня ровно такой же код в QA дает 2 резалтсета. Чем ты смотришь?
Здравствуйте Lexey, Вы писали:
L>Здравствуйте Алекс, Вы писали:
[MSDN можешь не цитировать.]
А>>Второй рекордсет у меня пустой. Т.е. его вообще нет. Nothing есть такое понятие в VB. Почему?
L>Пустой и вообще нет — совершенно разные вещи. Пустой — это BOF = EOF = TRUE.
Я же сказал — его нет вообще!
А>>Код следующий
А>>
А>>ALTER proc aa_proc as
А>>set nocount off
А>>select * from fff
А>>
L>У меня ровно такой же код в QA дает 2 резалтсета. Чем ты смотришь?
У меня тоже два результата. Один в виде рекордсета, другой в виде строки. Но на клиенте рекордсет один!
Dim r As Recordset, r1 As Recordset
Dim cmd As New Command
Set cmd.ActiveConnection = c
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "aa_proc"Set r = cmd.Execute
Do While Not r.EOF
Debug.Print r.Fields(0)
r.MoveNext
Loop
Set r1 = r.NextRecordset
If Not r1 Is Nothing Then
Do While Not r1.EOF
Debug.Print r1.Fields(0)
r1.MoveNext
Loop
End If
Если ты хоть чуть-чуть в VB шаришь, попробуй проверь, а после этого будем нулями кидаться.
Алекс, ты не прав.
Первый рекордсет ни на какую удаленную таблицу указывать не может... Все происходит именнто так как написал Lexey и как написано в MSDN. Тоесть первое выражение есть non–row-returning command и в рекордсете оказывается число строк, второй же рекордсет возвращает нужную нам таблицу. Команда SET NOCOUNT ON подавляет вывод служебной информации, что нам и надо, чтобы лишний раз по рекордсетам не елозить...
Твой же пример вполне себе row-returning...
Try this:
ALTER proc aa_proc as
set nocount off
select * into #tmp from fff
Dim r As Recordset, r1 As Recordset
Dim cmd As New Command
Set cmd.ActiveConnection = c
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "aa_proc"Set r = cmd.Execute
Do While Not r.EOF
Debug.Print r.Fields(0)
r.MoveNext
Loop
И доложи о результатах... )
А-то у меня VB под рукой нету... А>Если ты хоть чуть-чуть в VB шаришь, попробуй проверь, а после этого будем нулями кидаться.
Да, тут ты прав, ноль он тебе не за тот постинг поставил...
Здравствуйте Merle, Вы писали:
M>Здравствуйте Алекс, Вы писали:
M>Алекс, ты не прав. M>Первый рекордсет ни на какую удаленную таблицу указывать не может... Все происходит именнто так как написал Lexey и как написано в MSDN. Тоесть первое выражение есть non–row-returning command и в рекордсете оказывается число строк, второй же рекордсет возвращает нужную нам таблицу.
А-га уже первый рекордсет должен возвращать строку, а второй данные. Вы оба цитируете MSDN, а говорите разные вещи.
хъ
M>
M> ALTER proc aa_proc as
M> set nocount off
M> select * into #tmp from fff
M>
M> M>
M> Dim r As Recordset, r1 As Recordset
M> Dim cmd As New Command
M> Set cmd.ActiveConnection = c
M> cmd.CommandType = adCmdStoredProc
M> cmd.CommandText = "aa_proc"
M> Set r = cmd.Execute
M> Do While Not r.EOF
M> Debug.Print r.Fields(0)
M> r.MoveNext
M> Loop
M>
M>И доложи о результатах... )
Докладываю. Как ни странно это звучит, но никакой рекордсет не возвращается. Nothing по VB-ому говоря.
Здравствуйте Алекс, Вы писали:
А>У меня тоже два результата. Один в виде рекордсета, другой в виде строки. Но на клиенте рекордсет один!
Да, тут ты все-таки прав. Я зря разделил счетчик записей и рекордсет — OLE DB возвращает их вместе как один результат. ADO похоже оставляет только одно — либо рекордсет, если он есть, либо счетчик, если рекордсета нет.
QA умеет вытаскивать оба объекта.
А>Если ты хоть чуть-чуть в VB шаришь, попробуй проверь, а после этого будем нулями кидаться.
Ноль за тот пост я убрал, но в остальном ты все равно был не прав.
Здравствуйте Алекс, Вы писали:
M>>Алекс, ты не прав. M>>Первый рекордсет ни на какую удаленную таблицу указывать не может... Все происходит именнто так как написал Lexey и как написано в MSDN. Тоесть первое выражение есть non–row-returning command и в рекордсете оказывается число строк, второй же рекордсет возвращает нужную нам таблицу.
А>А-га уже первый рекордсет должен возвращать строку, а второй данные. Вы оба цитируете MSDN, а говорите разные вещи.
Ты опять что-то путаешь. Тут мы говорим ровно одно и тоже. По моим словам к этому должен был бы еще добавится третий рекордсет со строкой. Вот его действительно не будет.
хъ
L>Ноль за тот пост я убрал, но в остальном ты все равно был не прав.
Возможно. На самом деле (извини конечно) я тут тебя немного провоцировал. По другому от гуру ответа не добится.
Я уже задавал вопрос о том, по каким каналам можно получить информацию о кол-ве выбранных строк, как это делает QA. Возможно ли это с помощью ADO или OLEDB. Вот.
И еще. Непонятно как установка nocount помогла в вышеописанном случае.
Здравствуйте Алекс, Вы писали:
L>>Ноль за тот пост я убрал, но в остальном ты все равно был не прав.
А>Возможно. На самом деле (извини конечно) я тут тебя немного провоцировал. По другому от гуру ответа не добится.
Мда, проворакатор.
А>Я уже задавал вопрос о том, по каким каналам можно получить информацию о кол-ве выбранных строк, как это делает QA. Возможно ли это с помощью ADO или OLEDB. Вот.
Ну в общем-то, в OLE DB это описано в описании IMultipleResults.
А>И еще. Непонятно как установка nocount помогла в вышеописанном случае.
Да как раз все понятно. select .. into — это как раз та самая non-row-returning command. С nocount off она возвращает число обработанных записей, которое и попадает в первый рекордсет. Noucount on подавляет этот возврат.