Почему не выполняется SQL-запрос из 1С через ADODB и как это исправить?

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

Работа с внешними базами данных через COM-объект ADODB.Connection является классической задачей для разработчика 1С. Часто при попытке выполнить запрос, особенно когда в нем присутствуют фильтры по датам, возникает исключение на этапе вызова метода execute(). Давайте разберем, почему это происходит и как правильно организовать передачу данных.

Анализ причин ошибки

Основная причина возникновения ошибок при выполнении SQL-запросов через ADODB заключается в способе передачи параметров. Когда мы формируем строку запроса и подставляем в нее дату, отформатированную средствами 1С (например, dd-MM-yy), SQL-сервер может интерпретировать ее некорректно в зависимости от текущих региональных настроек (Language/DateFormat). Кроме того, попытка передать несколько команд (пакетный запрос) без должной подготовки среды часто приводит к сбоям.

Решение проблемы: правильное форматирование и передача дат

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

Для этого воспользуемся функцией CONVERT с указанием стиля 104 (это стандартный формат dd.mm.yyyy), что обеспечит гарантированное распознавание даты сервером.

Рассмотрим пошаговый пример реализации:

  1. Подготавливаем строки дат в 1С.
  2. Формируем текст SQL-запроса, используя плейсхолдеры для подстановки значений.
  3. Выполняем замену плейсхолдеров на подготовленные строки.
  4. Отправляем запрос на выполнение.

// Подготовка дат в 1С
ДатаНачала = "'" + Формат(НачалоПериода,"ДФ='dd/MM/yyyy HH:mm:ss'") + "'";
ДатаОкончания = "'" + Формат(КонецПериода,"ДФ='dd/MM/yyyy HH:mm:ss'") + "'";

// Формирование текста запроса с использованием CONVERT
СтрКоманда =
"SELECT CASE [TARGET_PLACE] When '1011100' Then 'Пила1' When '1011200' Then 'Пила2' End AS Saw
|[MATERIAL_NO] as Art
|,SUM(QUANTITY) as Quantity
|FROM [StorageManager].[dbo].[T3_MATERIALMOVEMENT]
|Where [SAVE_DATETIME] >= CONVERT(datetime, ДатаНачала, 104) 
|and [SAVE_DATETIME] <= CONVERT(datetime, ДатаОкончания, 104) 
|and [TARGET_PLACE] in ('1011100','1011200')
|Group by [TARGET_PLACE],[MATERIAL_NO]
|Order by [MATERIAL_NO]";

// Замена плейсхолдеров
СтрКоманда = СтрЗаменить(СтрКоманда,"ДатаНачала",ДатаНачала);
СтрКоманда = СтрЗаменить(СтрКоманда,"ДатаОкончания",ДатаОкончания);

Оптимизация работы с пакетными запросами

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

Чтобы избежать этой проблемы, рекомендуется добавлять в самое начало вашего SQL-скрипта команду SET NOCOUNT ON. Это отключит вывод служебных сообщений, оставив только результат выборки, что сделает работу с базой данных значительно стабильнее.

Важные рекомендации для разработчика

При отладке подобных задач всегда следуйте этим советам:

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

← На главную