При интеграции 1С со сторонними базами данных на базе SQL Server разработчики часто сталкиваются с ошибками типизации при передаче параметров в текст запроса. Разберем типичную ситуацию: из 1С в базу SQL выгружаются данные, при этом возникает ошибка Microsoft OLE DB Provider:
Conversion failed when converting the varchar value '2 018' to data type int.
Проанализируем причину такого поведения и рассмотрим несколько эффективных способов решения данной проблемы, от самых простых до профессиональных.
Посмотрим на исходный код формирования условия в тексте запроса, который вызвал ошибку:
ТекстУсловия = " AND dategood= '" + Формат(НаборЗаписей.Fields("dategood").Value, "ДФ=""гггг""") + "'";
Поле dategood в базе SQL имеет числовой тип (int), и в нем хранится год, например, 2018. Ошибка заключается в том, как платформа 1С по умолчанию работает с числами при приведении их к строке. Если мы попытаемся неявно преобразовать число больше 999 в строку (или используем неподходящую форматную строку), 1С автоматически добавит символ неразрывного пробела для разделения групп разрядов (тысяч, миллионов и т.д.).
В результате число 2018 превращается в строку "2 018" (с пробелом посередине). SQL Server, получая такую строку, не может корректно преобразовать ее в тип int, что и вызывает исключительную ситуацию. Использование формата даты ДФ=гггг в данном случае бессмысленно, так как исходное значение является числом, а не датой, поэтому функция Формат просто его игнорирует.
Давайте разберем по шагам, как правильно подготовить числовые данные для передачи в SQL-запрос.
Самый быстрый способ исправить ситуацию непосредственно в тексте запроса — явно указать платформе 1С, что число нужно форматировать без группировки разрядов. Для этого в форматной строке используется параметр ЧГ=0.
Также важно помнить, что SQL ожидает число, а не строку, поэтому одинарные кавычки вокруг значения в самом SQL-запросе необходимо убрать.
Рассмотрим правильный вариант кода:
ТекстУсловия = " AND dategood = " + Формат(НаборЗаписей.Fields("dategood").Value, "ЧГ=0");
В этом случае на выходе мы получим корректную строку AND dategood = 2018, которая успешно выполнится на сервере базы данных.
Если по какой-то причине вы не используете функцию Формат, а преобразуете число в строку другим способом, вы можете принудительно удалить неразрывные пробелы из полученной строки с помощью функции СтрЗаменить и системного перечисления Символы.
Посмотрим на пример реализации:
ЗначениеСтрока = Строка(НаборЗаписей.Fields("dategood").Value);
ЗначениеБезПробелов = СтрЗаменить(ЗначениеСтрока, Символы.НПП, "");
ТекстУсловия = " AND dategood = " + ЗначениеБезПробелов;
Этот метод рабочий, но менее изящный, чем настройка форматной строки.
При формировании текстов запросов, XML-файлов или JSON-структур для внешних систем, лучшей практикой в 1С является использование встроенной функции XMLСтрока. Эта функция предназначена специально для того, чтобы приводить базовые типы 1С (числа, даты, булево) к стандартизированному строковому представлению без локальных особенностей (таких как пробелы в числах или русские названия месяцев).
Применим этот подход к нашей задаче:
ТекстУсловия = " AND dategood = " + XMLСтрока(НаборЗаписей.Fields("dategood").Value);
Функция гарантированно вернет строку "2018" без пробелов, что делает код более чистым и устойчивым к ошибкам.
Формирование SQL-запросов путем склеивания (конкатенации) строк является плохой практикой из-за проблем с форматированием и уязвимости к SQL-инъекциям. Если вы используете объект ADO для связи с базой данных, давайте перейдем на использование объекта ADODB.Command и передачу параметров.
Разберем этот метод подробнее:
Команда = Новый COMОбъект("ADODB.Command");
Команда.ActiveConnection = ВашеСоединение;
Команда.CommandText = "SELECT * FROM TableName WHERE dategood = ?";
// Передаем значение напрямую, без преобразования в строку
Параметр = Команда.CreateParameter("dategood", 3, 1, , НаборЗаписей.Fields("dategood").Value); // 3 - тип adInteger
Команда.Parameters.Append(Параметр);
Выборка = Команда.Execute();
При таком подходе OLE DB Provider сам выполняет корректное преобразование типов между 1С и SQL Server. Нам больше не нужно заботиться о неразрывных пробелах, удалении кавычек или формате дат.
Проанализируем еще один важный нюанс. Если в переменной 1С содержится пустое значение (например, 0 или незаполненное поле), преобразование этого значения в строку для SQL-запроса может привести к пустой строке, что снова вызовет ошибку.
Обязательно добавляйте проверку на заполненность значения перед формированием строки запроса:
ЗначениеГода = НаборЗаписей.Fields("dategood").Value;
Если ЗначениеЗаполнено(ЗначениеГода) Тогда
ТекстУсловия = " AND dategood = " + XMLСтрока(ЗначениеГода);
Иначе
// Обработка ситуации, если год не указан (например, передача NULL)
ТекстУсловия = " AND dategood IS NULL";
КонецЕсли;
Подведем итоги: для корректной передачи чисел из 1С в тексты SQL-запросов всегда избавляйтесь от неразрывных пробелов (используя ЧГ=0 или XMLСтрока), не берите числовые значения в кавычки в самом SQL-запросе, а для сложных интеграций используйте параметризованные запросы ADO.