Как исправить ошибку конвертации строки в число при передаче данных из 1С в SQL Server?

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

При интеграции 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: Использование функции Формат для отключения разделителей

Самый быстрый способ исправить ситуацию непосредственно в тексте запроса — явно указать платформе 1С, что число нужно форматировать без группировки разрядов. Для этого в форматной строке используется параметр ЧГ=0.

Также важно помнить, что SQL ожидает число, а не строку, поэтому одинарные кавычки вокруг значения в самом SQL-запросе необходимо убрать.

Рассмотрим правильный вариант кода:


ТекстУсловия = " AND dategood = " + Формат(НаборЗаписей.Fields("dategood").Value, "ЧГ=0");

В этом случае на выходе мы получим корректную строку AND dategood = 2018, которая успешно выполнится на сервере базы данных.

Способ 2: Замена неразрывного пробела

Если по какой-то причине вы не используете функцию Формат, а преобразуете число в строку другим способом, вы можете принудительно удалить неразрывные пробелы из полученной строки с помощью функции СтрЗаменить и системного перечисления Символы.

Посмотрим на пример реализации:


ЗначениеСтрока = Строка(НаборЗаписей.Fields("dategood").Value);
ЗначениеБезПробелов = СтрЗаменить(ЗначениеСтрока, Символы.НПП, "");
ТекстУсловия = " AND dategood = " + ЗначениеБезПробелов;

Этот метод рабочий, но менее изящный, чем настройка форматной строки.

Способ 3: Использование функции XMLСтрока (Рекомендуемый для конкатенации)

При формировании текстов запросов, XML-файлов или JSON-структур для внешних систем, лучшей практикой в 1С является использование встроенной функции XMLСтрока. Эта функция предназначена специально для того, чтобы приводить базовые типы 1С (числа, даты, булево) к стандартизированному строковому представлению без локальных особенностей (таких как пробелы в числах или русские названия месяцев).

Применим этот подход к нашей задаче:


ТекстУсловия = " AND dategood = " + XMLСтрока(НаборЗаписей.Fields("dategood").Value);

Функция гарантированно вернет строку "2018" без пробелов, что делает код более чистым и устойчивым к ошибкам.

Способ 4: Использование параметризованных запросов (Профессиональный подход)

Формирование 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. Нам больше не нужно заботиться о неразрывных пробелах, удалении кавычек или формате дат.

Обработка пустых значений (NULL)

Проанализируем еще один важный нюанс. Если в переменной 1С содержится пустое значение (например, 0 или незаполненное поле), преобразование этого значения в строку для SQL-запроса может привести к пустой строке, что снова вызовет ошибку.

Обязательно добавляйте проверку на заполненность значения перед формированием строки запроса:


ЗначениеГода = НаборЗаписей.Fields("dategood").Value;

Если ЗначениеЗаполнено(ЗначениеГода) Тогда
    ТекстУсловия = " AND dategood = " + XMLСтрока(ЗначениеГода);
Иначе
    // Обработка ситуации, если год не указан (например, передача NULL)
    ТекстУсловия = " AND dategood IS NULL";
КонецЕсли;

Подведем итоги: для корректной передачи чисел из 1С в тексты SQL-запросов всегда избавляйтесь от неразрывных пробелов (используя ЧГ=0 или XMLСтрока), не берите числовые значения в кавычки в самом SQL-запросе, а для сложных интеграций используйте параметризованные запросы ADO.

← На главную