При интеграции 1С с внешними базами данных Microsoft SQL Server часто возникает необходимость вызова хранимых процедур и получения кода результата их работы (оператора RETURN). В стандартной практике при вызове команды через ADODB.Command значение Parameters("RETURN_VALUE").Value может возвращать NULL или Неопределено. Разберем по шагам, как правильно настроить объекты ADO в 1С, перехватить возвращаемое значение и обработать ошибки выполнения.
Для корректной передачи параметров и получения кода возврата выполним настройку объекта ADODB.Command. Проанализируем ключевые особенности этой настройки:
CommandType должен принимать значение 4 (что соответствует adCmdStoredProc). При этом в свойство CommandText передается только имя хранимой процедуры без управляющих ключевых слов T-SQL.adParamReturnValue (числовой код 4) должен быть создан и добавлен в коллекцию Parameters самым первым (с нулевым индексом).Execute, если процедура возвращает набор данных (Recordset), его необходимо закрыть методом Close() до обращения к значениям параметров.Рассмотрим пример кода 1С для вызова хранимой процедуры с получением результата:
Соединение = Новый COMОбъект("ADODB.Connection");
Команда = Новый COMОбъект("ADODB.Command");
Попытка
Соединение.Open(СтрокаСоединения);
Команда.ActiveConnection = Соединение;
Команда.CommandTimeOut = 600;
// Указываем тип команды: 4 = adCmdStoredProc
Команда.CommandType = 4;
Команда.CommandText = "ИмяХранимойПроцедуры";
// 1. Первым добавляем параметр для RETURN_VALUE (adInteger = 3, adParamReturnValue = 4)
ПараметрВозврата = Команда.CreateParameter("RETURN_VALUE", 3, 4, , NULL);
Команда.Parameters.Append(ПараметрВозврата);
// 2. Добавляем входные параметры (adVarChar = 200, adParamInput = 1)
Параметр1 = Команда.CreateParameter("repIDD", 200, 1, 50, ЗначениеIDD);
Команда.Parameters.Append(Параметр1);
// Выполняем процедуру
Записи = Команда.Execute();
// Если сформирован открытый Recordset, перед чтением параметров его нужно закрыть
Если Записи <> Неопределено И Записи.State = 1 Тогда // 1 = adStateOpen
Записи.Close();
КонецЕсли;
// Считываем результат работы процедуры
РезультатВыполнения = Команда.Parameters("RETURN_VALUE").Value;
Сообщить("Код возврата ХП: " + Строка(РезультатВыполнения));
Исключение
ТекстОшибки = ОписаниеОшибки();
ВызватьИсключение "Ошибка при выполнении хранимой процедуры: " + ТекстОшибки;
КонецПопытки;
Выясним основные причины, по которым параметр возврата не заполняется на стороне 1С:
SET NOCOUNT ON в процедуре SQL. Если в теле хранимой процедуры выполняются операторы INSERT, UPDATE или DELETE, MS SQL Server отправляет сообщения о количестве обработанных строк. ADO воспринимает их как служебные наборы данных, что блокирует заполнение коллекции Parameters. Обязательно добавляйте SET NOCOUNT ON; в начало T-SQL кода процедуры.adParamReturnValue обязательно должен создаваться и добавляться в Command.Parameters первым по порядку.RETURN_VALUE становятся доступны на стороне клиента только после закрытия или полного прочтения возвращаемого набора записей.Если настройка коллекции Parameters вызывает сложности или тип данных параметра не удается согласовать с OLE DB, применим более простой и надежный способ — перехват значения RETURN через обертку в T-SQL запрос. В этом случае свойство CommandType устанавливается в значение 1 (adCmdText):
Соединение = Новый COMОбъект("ADODB.Connection");
Команда = Новый COMОбъект("ADODB.Command");
Соединение.Open(СтрокаСоединения);
Команда.ActiveConnection = Соединение;
Команда.CommandType = 1; // adCmdText
Команда.CommandText =
"DECLARE @RC int;
|EXEC @RC = ИмяХранимойПроцедуры @Param1 = '" + Строка(Значение1) + "';
|SELECT @RC AS ReturnValue;";
Записи = Команда.Execute();
Если Не Записи.EOF() Тогда
РезультатВыполнения = Записи.Fields("ReturnValue").Value;
Сообщить("Код возврата ХП: " + Строка(РезультатВыполнения));
КонецЕсли;
При отладке вызова COM-объектов стандартная функция ОписаниеОшибки() может выводить пустую строку из-за особенностей перехвата исключением со стороны COM. Для детальной диагностики ошибок SQL Server рекомендуем сохранять описание ошибки в переменную внутри блока Исключение или обращаться к коллекции Connection.Errors:
Попытка
Записи = Команда.Execute();
Исключение
ТекстОшибки = ОписаниеОшибки();
// Чтение подробного описания из коллекции ошибок ADO
Если Соединение.Errors.Count > 0 Тогда
Для Индекс = 0 По Соединение.Errors.Count - 1 Цикл
ТекстОшибки = ТекстОшибки + Символы.ПС + Соединение.Errors.Item(Индекс).Description;
КонецЦикла;
КонецЕсли;
ВызватьИсключение "Сбой выполнения ADO: " + ТекстОшибки;
КонецПопытки;