Как получить возвращаемое значение хранимой процедуры SQL Server через COM-соединение в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешними базами данных Microsoft SQL Server часто используется прямое подключение через COM-объекты ADODB.Connection и ADODB.Command. Типичная задача — запустить хранимую процедуру и получить результат ее работы. Однако нередко разработчики сталкиваются с ситуацией, когда метод Execute() возвращает объект Recordset, но количество полей в нем равно нулю (RS.Fields.Count = 0), а обращение к значениям вызывает ошибку контекста.

Разберем причины такого поведения и рассмотрим подробные способы получения результата выполнения процедуры.

Выясним причину: почему Recordset возвращается пустым

В MS SQL Server результат работы процедуры может формироваться несколькими способами:

  1. Результирующий набор данных (оператор SELECT): процедура возвращает строки таблицы. Если внутри процедуры выполняются операции INSERT, UPDATE или DELETE без директивы SET NOCOUNT ON, SQL Server отправляет клиенту служебные сообщения о количестве обработанных строк. Провайдер ADODB воспринимает каждое такое сообщение как отдельный закрытый набор записей, из-за чего первый полученный Recordset оказывается пустым.
  2. Код возврата (оператор RETURN): процедура возвращает целочисленный статус. Данный код не попадает в выборку Recordset, а возвращается через специальный системный параметр команды.
  3. Выходные параметры (директива OUTPUT): данные передаются обратно через именованные переменные процедуры.

Способ 1. Корректный обход набора записей (Recordset)

Если хранимая процедура возвращает данные через оператор SELECT, для чтения значений необходимо спозиционироваться на первой строке выборки и последовательно обойти строки с помощью методов MoveFirst() и MoveNext().

Посмотрим на пример корректного чтения данных:


// Предполагается, что RS получен в результате Command.Execute()
Если RS.State = 1 Тогда // 1 = adStateOpen (набор открыт)
    Если Не RS.EOF Тогда
        RS.MoveFirst();
        Пока Не RS.EOF Цикл
            // Получаем значение первой колонки (индексация с 0)
            ВозвращаемоеЗначение = RS.Fields(0).Value;
            
            // Выполняем переход к следующей записи
            RS.MoveNext();
        КонецЦикла;
    КонецЕсли;
КонецЕсли;

Способ 2. Пропуск промежуточных наборов с помощью NextRecordset

Если текст процедуры недоступен для редактирования и в ней происходят промежуточные манипуляции с данными без подавления счетчиков строк, необходимо перебрать наборы данных до тех пор, пока не будет найден открытый Recordset с реальными полями.

Разберем по шагам, как организовать безопасный перебор наборов:


Пока RS <> Неопределено И RS.State <> 0 Цикл
    // Проверяем, содержит ли текущий набор поля
    Если RS.Fields.Count > 0 Тогда
        Если Не RS.EOF Тогда
            RS.MoveFirst();
            ВозвращаемоеЗначение = RS.Fields(0).Value;
            Прервать;
        КонецЕсли;
    КонецЕсли;
    
    // Переходим к следующему результирующему набору
    RS = RS.NextRecordset();
КонецЦикла;

Способ 3. Переопределение запроса с явным SELECT (универсальный вариант)

Когда исходный код процедуры закрыт и неизвестно, как именно она возвращает статус (через RETURN или выходной параметр), самым простым решением является вызов процедуры внутри короткого скрипта T-SQL с явным выводом результата в SELECT и отключением служебных сообщений.

Рассмотрим пример формирования такой команды:


Команда = Новый COMОбъект("ADODB.Command");
Команда.ActiveConnection = Соединение;
Команда.CommandType = 1; // 1 = adCmdText

// Заворачиваем вызов в скрипт T-SQL
ТекстЗапроса = 
"SET NOCOUNT ON;
|DECLARE @Result INT;
|EXEC @Result = dbo.ИмяПроцедуры;
|SELECT @Result AS ReturnCode;";

Команда.CommandText = ТекстЗапроса;
RS = Команда.Execute();

Если RS.State = 1 И Не RS.EOF Тогда
    ВозвращаемоеЗначение = RS.Fields("ReturnCode").Value;
    RS.Close();
КонецЕсли;

Способ 4. Получение кода возврата через параметр ADODB (adParamReturnValue)

Если известно, что процедура использует стандартный механизм RETURN <значение>, значение можно прочитать напрямую через коллекцию параметров Parameters объекта ADODB.Command.

Разберем настройку команды с параметром возврата:


Команда = Новый COMОбъект("ADODB.Command");
Команда.ActiveConnection = Соединение;
Команда.CommandText = "dbo.ИмяПроцедуры";
Команда.CommandType = 4; // 4 = adCmdStoredProc

// Создаем параметр для кода возврата:
// Имя: "ReturnValue"
// Тип: 3 (adInteger)
// Направление: 4 (adParamReturnValue)
ПараметрВозврата = Команда.CreateParameter("ReturnValue", 3, 4);
Команда.Parameters.Append(ПараметрВозврата);

RS = Команда.Execute();

// Если процедура возвращала и Recordset, его нужно закрыть,
// чтобы гарантировать заполнение параметров
Если RS.State = 1 Тогда
    RS.Close();
КонецЕсли;

КодВозврата = Команда.Parameters("ReturnValue").Value;

Особенности и ограничения платформы 1С:Предприятие

При использовании COM-объектов ADODB важно помнить о следующих нюансах:

  1. Зависимость от операционной системы: COM-технология доступна исключительно в среде Windows. Если сервер 1С работает под управлением ОС Linux, вызовы COM-объектов завершатся ошибкой.
  2. Разрядность драйверов (провайдеров): если код выполняется на стороне 64-разрядного сервера 1С, в операционной системе обязательно должен быть установлен 64-битный провайдер доступа к данным (например, MSOLEDBSQL или SQLNCLI11).
  3. Штатная альтернатива: для платформенной интеграции без COM-объектов рекомендуется использовать встроенный механизм 1С «Внешние источники данных», который работает кроссплатформенно и позволяет подключаться к внешним таблицам и процедурам через ODBC.
← На главную