При работе с внешними SQL-базами данных из среды 1С 7.7 через объект ADODB.Command или ADODB.Recordset часто возникает задача — заранее узнать, сколько именно записей вернул запрос. Многие разработчики сталкиваются с тем, что стандартное свойство RecordCount возвращает значение -1. Давайте разберемся, почему так происходит и какие существуют эффективные способы решения этой задачи.
Проблема кроется в настройках курсора (cursor) объекта Recordset. По умолчанию ADO открывает набор данных в режиме adOpenForwardOnly (последовательный курсор). Этот режим является наиболее производительным, так как данные считываются последовательно «на лету» без кэширования всей выборки в памяти. Поскольку система не знает заранее, сколько строк будет прочитано, свойство RecordCount возвращает значение -1 как индикатор того, что размер выборки неизвестен.
Самый простой и надежный метод — выполнить два отдельных запроса. Первый запрос вернет количество строк, соответствующих вашему условию, а второй — сами данные. Это не требует изменения настроек курсоров и работает на любом провайдере данных.
Рассмотрим пример кода:
// Запрос для получения количества записей
Cmd.Commandtext = "SELECT COUNT(*) FROM SC2463 WHERE (ISMARK=0 and SP2464 = ' 22I ')";
Rs = Cmd.Execute();
КоличествоСтрок = Rs.Fields(0).Value;
Сообщить("Всего записей: " + КоличествоСтрок);
// Запрос для получения самих данных
Cmd.Commandtext = "SELECT CODE FROM SC2463 WHERE (ISMARK=0 and SP2464 = ' 22I ')";
Rs = Cmd.Execute();
Этот подход максимально эффективен с точки зрения ресурсов сервера, так как COUNT(*) выполняется крайне быстро.
Если вы все же хотите получить количество записей непосредственно из объекта Recordset, необходимо принудительно указать тип курсора, поддерживающий навигацию и подсчет, например adOpenStatic или adOpenKeyset. Однако стоит учитывать, что это увеличит нагрузку на оперативную память сервера, так как вся выборка будет загружена в клиентский кэш.
Для корректной работы с курсором необходимо использовать объект ADODB.Recordset вместо ADODB.Command.Execute, так как именно метод Open позволяет передать параметры курсора:
Rs = СоздатьОбъект("ADODB.Recordset");
// 3 - adOpenStatic, 1 - adLockReadOnly
Rs.Open(ТекстЗапроса, Соединение, 3, 1);
Количество = Rs.RecordCount;
Если вы работаете с MS SQL Server, можно получить общее количество строк прямо в процессе выборки данных, используя оконную функцию COUNT(*) OVER(). Это позволит вам узнать размер всей выборки, не выполняя дополнительных запросов.
SELECT
CODE,
COUNT(*) OVER() as TotalCount
FROM SC2463
WHERE (ISMARK=0 and SP2464 = ' 22I ')
При обходе такой выборки значение TotalCount будет присутствовать в каждой строке, что дает вам информацию об общем объеме данных сразу после начала цикла.
Проанализируем ситуацию: какой метод выбрать в вашей задаче?
SELECT COUNT(*)). Это классика программирования на 1С 7.7.Подводя итог, можно сказать, что ситуация с RecordCount = -1 — это не ошибка, а особенность оптимизации ADO. Выбирая один из предложенных подходов, вы сможете уверенно управлять выборками данных в своих обработках и отчетах.