Как узнать количество записей в SQL-запросе через ADO в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При работе с внешними SQL-базами данных из среды 1С 7.7 через объект ADODB.Command или ADODB.Recordset часто возникает задача — заранее узнать, сколько именно записей вернул запрос. Многие разработчики сталкиваются с тем, что стандартное свойство RecordCount возвращает значение -1. Давайте разберемся, почему так происходит и какие существуют эффективные способы решения этой задачи.

Почему RecordCount возвращает -1?

Проблема кроется в настройках курсора (cursor) объекта Recordset. По умолчанию ADO открывает набор данных в режиме adOpenForwardOnly (последовательный курсор). Этот режим является наиболее производительным, так как данные считываются последовательно «на лету» без кэширования всей выборки в памяти. Поскольку система не знает заранее, сколько строк будет прочитано, свойство RecordCount возвращает значение -1 как индикатор того, что размер выборки неизвестен.

Способ №1: Использование предварительного запроса COUNT

Самый простой и надежный метод — выполнить два отдельных запроса. Первый запрос вернет количество строк, соответствующих вашему условию, а второй — сами данные. Это не требует изменения настроек курсоров и работает на любом провайдере данных.

Рассмотрим пример кода:


// Запрос для получения количества записей
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(*) выполняется крайне быстро.

Способ №2: Изменение типа курсора

Если вы все же хотите получить количество записей непосредственно из объекта Recordset, необходимо принудительно указать тип курсора, поддерживающий навигацию и подсчет, например adOpenStatic или adOpenKeyset. Однако стоит учитывать, что это увеличит нагрузку на оперативную память сервера, так как вся выборка будет загружена в клиентский кэш.

Для корректной работы с курсором необходимо использовать объект ADODB.Recordset вместо ADODB.Command.Execute, так как именно метод Open позволяет передать параметры курсора:


Rs = СоздатьОбъект("ADODB.Recordset");
// 3 - adOpenStatic, 1 - adLockReadOnly
Rs.Open(ТекстЗапроса, Соединение, 3, 1);
Количество = Rs.RecordCount;

Способ №3: Использование оконных функций SQL

Если вы работаете с MS SQL Server, можно получить общее количество строк прямо в процессе выборки данных, используя оконную функцию COUNT(*) OVER(). Это позволит вам узнать размер всей выборки, не выполняя дополнительных запросов.


SELECT 
    CODE, 
    COUNT(*) OVER() as TotalCount 
FROM SC2463 
WHERE (ISMARK=0 and SP2464 = '  22I  ')

При обходе такой выборки значение TotalCount будет присутствовать в каждой строке, что дает вам информацию об общем объеме данных сразу после начала цикла.

Рекомендации по выбору метода

Проанализируем ситуацию: какой метод выбрать в вашей задаче?

  1. Если выборка небольшая и вы хотите сохранить простоту кода — используйте Способ №1 (предварительный SELECT COUNT(*)). Это классика программирования на 1С 7.7.
  2. Если вы активно работаете с SQL-запросами и готовы к усложнению архитектуры — рассмотрите использование компоненты 1С++. Она дает гораздо больше гибкости при работе с SQL-запросами в 7.7, позволяя использовать объекты, более привычные для данной платформы.
  3. Если вы ограничены в ресурсах памяти — избегайте изменения типов курсора (Способ №2) на больших объемах данных, так как это может привести к «зависанию» клиентского приложения 1С при попытке загрузить миллионы строк в память.

Подводя итог, можно сказать, что ситуация с RecordCount = -1 — это не ошибка, а особенность оптимизации ADO. Выбирая один из предложенных подходов, вы сможете уверенно управлять выборками данных в своих обработках и отчетах.

← На главную