Глюк с RecordCount

Работа VB и СУБД (Access, MSSQL, MySQL, Oracle и пр.)
Правила форума
При создании новой темы не забывайте указывать используемую СУБД.
Netta
Новичок
Новичок
 
Сообщения: 37
Зарегистрирован: 25.11.2003 (Вт) 12:22
Откуда: Lithuanian

Глюк с RecordCount

Сообщение Netta » 17.04.2005 (Вс) 14:20

Объясните плиззз, простой запрос, а количество записей почему-то возврашает -1, хотя в табличке 4. Где ошибка????


Dim db As ADODB.Recordset
Set db = CurrentProject.Connection.Execute("select semestrID, data from semestр")
MsgBox CStr(db.RecordCount)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.04.2005 (Вс) 14:36

Потому что курсор серверный.
Укажи клиентский курсор и будет давать актуальные данные.
Lasciate ogni speranza, voi ch'entrate.

Netta
Новичок
Новичок
 
Сообщения: 37
Зарегистрирован: 25.11.2003 (Вт) 12:22
Откуда: Lithuanian

Сообщение Netta » 17.04.2005 (Вс) 14:39

alibek писал(а):Потому что курсор серверный.
Укажи клиентский курсор и будет давать актуальные данные.


Если не трудно, объясните чайнику, как это сделать :oops:

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.04.2005 (Вс) 14:46

Код: Выделить всё
Dim rst As ADODB.Recordset
...
Set rst = New ADODB.Recordset
Set rst.ActiveConnection = CurrentProject.Connection
rst.CursorLocation = adUseClient
rst.Open "select semestrID, data from semestр"
MsgBox rst.RecordCount
Lasciate ogni speranza, voi ch'entrate.

Andrew Sherd
Новичок
Новичок
Аватара пользователя
 
Сообщения: 42
Зарегистрирован: 10.05.2004 (Пн) 0:18
Откуда: Санкт-Петербург

Сообщение Andrew Sherd » 20.05.2005 (Пт) 7:57

Хм... у меня примерно такая же ситуевина... толко не помог перенос курсора на сторону пользователя...

все равно выдает -1... иногда правда это лечится командоми типа:

Код: Выделить всё
rst.MoveLast
st.MoveFirst


Но это уже больше похоже на шаманские пляски на лугу, чем на программирование...

Кто-нить откомментирует?

P.S. У меня MS SQL Server 2000
Маленькие хитрости: Если золотую рыбку положить на сковородку, количество желаний увеличивается да 50!!!

snov
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 176
Зарегистрирован: 28.11.2003 (Пт) 10:12
Откуда: Челябинск

Сообщение snov » 20.05.2005 (Пт) 8:09

Andrew Sherd писал(а):Хм... у меня примерно такая же ситуевина... толко не помог перенос курсора на сторону пользователя...

Такой баг только в DAO видел, вроде ADO нету этого

Andrew Sherd
Новичок
Новичок
Аватара пользователя
 
Сообщения: 42
Зарегистрирован: 10.05.2004 (Пн) 0:18
Откуда: Санкт-Петербург

Сообщение Andrew Sherd » 20.05.2005 (Пт) 10:58

Все-таки программирование - это магия...

RecordCount работает с ADO до выполнения запроса... после выдает -1

Выхожу из ситуации просто - замарачиваться нету времени, поэтому написал простую функцию, которую и юзаю везде:

Код: Выделить всё

Public Function RecCount(rs As ADODB.Recordset) As Long
Dim i As Long
Do
    i = i + 1
    rs.MoveNext
Loop While Not rs.EOF
RecCount = i
End Function
Маленькие хитрости: Если золотую рыбку положить на сковородку, количество желаний увеличивается да 50!!!

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 20.05.2005 (Пт) 11:03

лучше так не делать - сильно тормозить будет на больших объемах
выполняй тогда
Код: Выделить всё
SELECT Count(*) from (твой селект) A


вообще-то если курсор клиентский, то recordcount должен быть - покажи свой код, где ты открываешь рекордсет

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 20.05.2005 (Пт) 11:06

может ты рекордсет получаешь из хранимой процедуры :?: тогда проверь наличие строчек в ней
Код: Выделить всё
SET NOCOUNT ON
, перед выдачей рекордсета должне стоять
Код: Выделить всё
SET NOCOUNT OFF

Andrew Sherd
Новичок
Новичок
Аватара пользователя
 
Сообщения: 42
Зарегистрирован: 10.05.2004 (Пн) 0:18
Откуда: Санкт-Петербург

Сообщение Andrew Sherd » 25.05.2005 (Ср) 4:54

Вот простой пример...
Последние два МсгБокс'а выдают "-1"

Код: Выделить всё

Dim Base As ADODB.Connection
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Set base = New ADODB.Connection
Set rs = New ADODB.Recordset
Set cmd = New ADODB.Command

Const CONNSTR1 As String = "Provider=SQLOLEDB;Persist Security Info=False;User ID=sa;Initial Catalog="
Const CONNSTR2 As String = ";Data Source="

base.Open CONNSTR1 & "ИМЯ_БАЗЫ" & CONNSTR2 & "ИМЯ_СЕРВЕРА", "ЛОГИН", "ПАРОЛЬ"
rs.ActiveConnection = a

rs.CursorLocation = adUseClient
rs.LockType = adLockOptimistic
rs.CursorType = adOpenDynamic
rs.Open "SELECT * FROM [Questions]"

cmd.ActiveConnection = base
cmd.CommandType = adCmdText

cmd.CommandText = "SELECT * FROM [Questions] WHERE TID=2"
Set rs = cmd.Execute

MsgBox rs.RecordCount
MsgBox rs.AbsolutePosition
Маленькие хитрости: Если золотую рыбку положить на сковородку, количество желаний увеличивается да 50!!!

codemaster
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 604
Зарегистрирован: 13.02.2004 (Пт) 13:35

Сообщение codemaster » 25.05.2005 (Ср) 9:40

Andrew Sherd писал(а):Вот простой пример...
Последние два МсгБокс'а выдают "-1"




Что пишет rs.State ?
//<-
Mit freundlichen Grüßen
//->

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 25.05.2005 (Ср) 9:42

Вообще-то, любые запросы, полученные через cmd.Execute, являются серверными, проверь rs.CursorLocation и удивись. Поэтому и RecordCount=-1.
Lasciate ogni speranza, voi ch'entrate.

codemaster
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 604
Зарегистрирован: 13.02.2004 (Пт) 13:35

Сообщение codemaster » 25.05.2005 (Ср) 9:48

alibek писал(а):Вообще-то, любые запросы, полученные через cmd.Execute, являются серверными, проверь rs.CursorLocation и удивись. Поэтому и RecordCount=-1.


еще 10 копеек

http://www.rsdn.ru/Forum/Message.aspx?mid=120628&only=1

правда стоит почитать всю ветку
//<-
Mit freundlichen Grüßen
//->

Andrew Sherd
Новичок
Новичок
Аватара пользователя
 
Сообщения: 42
Зарегистрирован: 10.05.2004 (Пн) 0:18
Откуда: Санкт-Петербург

Сообщение Andrew Sherd » 25.05.2005 (Ср) 9:55

Так и как это лечится....
прости те уж назойливость ньюба :D
Маленькие хитрости: Если золотую рыбку положить на сковородку, количество желаний увеличивается да 50!!!

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 25.05.2005 (Ср) 9:57

Думаю, что это как-то лечится. Скорее всего указанием опций в ADODB.Command. Вот только, что конкретно, не скажу, пока еще разбираться не доводилось.
Lasciate ogni speranza, voi ch'entrate.

codemaster
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 604
Зарегистрирован: 13.02.2004 (Пт) 13:35

Сообщение codemaster » 25.05.2005 (Ср) 9:59

Andrew Sherd писал(а):Так и как это лечится....
прости те уж назойливость ньюба :D


Тебе же написали - что возвращает rs.State ?
//<-
Mit freundlichen Grüßen
//->

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 25.05.2005 (Ср) 11:29

Подозреваю, что это связано с т.н. "препарированным" (prepared) SQL. В своей практике я замечал, что профайлер ловит на сервере какую-то херь вместо того, что я ему отправил. Как следствие, в некоторых случаях это приводило к ошибке вроде бы гарантированно работающего запроса.

Дабы не быть голословным, вот пример. Есть запрос (реальный, можете проверить сами):
Код: Выделить всё
exec master.dbo.xp_cmdshell '"D:\lab.cmd"'

Если я выполняю этот запрос из QA, то все окей, командный файл реально запускается и запрос возвращает результат его выполнения. Если же я выполняю его из своей программы (VB6, ADO 2.8 ), то - that depends. Поскольку на самом деле меня не интересует рекордсет, который мне возвратит xp_cmdshell, а интересует всего лишь старт этого батника, то у меня есть 2 пути: открыть рекордсет через его метод Open (довольно глупо, не правда ли?), или же выполнить этот запрос на коннекшне, в методе Execute (ну или в аналогичном методе объекта Command, но это просто взгляд в профиль на то же самое :) ). Так вот, если я запускаю его через рекордсет с опцией adCmdText, то на сервер приходит в точности указанный выше текст. А вот если использовать Execute, то на сервер приходит вот что:
Код: Выделить всё
declare @P1 int
set @P1=0
declare @P2 int
set @P2=16388
declare @P3 int
set @P3=8193
declare @P4 int
set @P4=0
exec sp_cursoropen @P1 output, N'exec master.dbo.xp_cmdshell ''"d:\lab.cmd"''', @P2 output, @P3 output, @P4 output
select @P1, @P2, @P3, @P4

Вышеприведенная обертка моего запроса в ненавязчивый вызов sp_cursoropen и есть, подозреваю, не что иное, как пресловутый "серверный курсор" :). В этом случае мы не получаем ничего: ни корректного значения RecordCount, ни просто корректного выполнения - данный конкретный пример валится с ошибкой "Cursor was not declared", появляющейся где-то в недрах xp_cmdshell. Проверялось на MSSQL 2000 SP3/SP4.

Вывод: если вым нужен RecordCount, открывайте рекордсет егойным методом Open, а никак не в виде результата выполнения метода Execute объектов Connection или Command. Оно надежнее будет, да и настроить свойства объекта можно заранее, до его открытия.

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 25.05.2005 (Ср) 13:36

у тебя проблема вот в этой строчке:

Код: Выделить всё
Set rs = cmd.Execute


ее надо заменить на вот это:

Код: Выделить всё
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.Open cmd,,adOpenStatic, adLockReadOnly, adCmdText

Andrew Sherd
Новичок
Новичок
Аватара пользователя
 
Сообщения: 42
Зарегистрирован: 10.05.2004 (Пн) 0:18
Откуда: Санкт-Петербург

Сообщение Andrew Sherd » 26.05.2005 (Чт) 16:55

Тебе же написали - что возвращает rs.State ?


rs.State возвращет 1

Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.Open cmd,,adOpenStatic, adLockReadOnly, adCmdText


Суть в том, что рекордсет, ктороый работает с данной таблицей у меня уже открыт. Предположим я делаю выборку SQL-запросом - и его результаты я должен обрабатывать уже в другом!? Или закрывать и вновь открывать текущий?
Маленькие хитрости: Если золотую рыбку положить на сковородку, количество желаний увеличивается да 50!!!

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 26.05.2005 (Чт) 17:09

Предположим я делаю выборку SQL-запросом - и его результаты я должен обрабатывать уже в другом!? Или закрывать и вновь открывать текущий?


что в другом?
объясни , что тебе нужно получить, т.е. каков результат всех втоих действий - вывод на экран в гриде, сохранение в базу, изменение данных и тд и тп

blinow
Обычный пользователь
Обычный пользователь
 
Сообщения: 53
Зарегистрирован: 27.06.2005 (Пн) 3:13

Сообщение blinow » 27.06.2005 (Пн) 4:05

Konst One все правильно написал, если тебя так интересует Recordciunt то переходи на такой синтаксис, или используй хранимые процедуры на сервере.
Если что-то часто вызывать делай индексы, делай процедуры подсчета записей в выборке и процедуры выборки, работает шустро если правильно спроектировать БД, но с использованием процедур еще один ньанс Recorset двигается только вперед и не шагу назад, тоже необходимо учитывать это.


Вернуться в Базы данных

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

    TopList