Работа с внешними базами данных через COM-объект ADODB.Connection является классической задачей для разработчика 1С. Часто при попытке выполнить запрос, особенно когда в нем присутствуют фильтры по датам, возникает исключение на этапе вызова метода execute(). Давайте разберем, почему это происходит и как правильно организовать передачу данных.
Основная причина возникновения ошибок при выполнении SQL-запросов через ADODB заключается в способе передачи параметров. Когда мы формируем строку запроса и подставляем в нее дату, отформатированную средствами 1С (например, dd-MM-yy), SQL-сервер может интерпретировать ее некорректно в зависимости от текущих региональных настроек (Language/DateFormat). Кроме того, попытка передать несколько команд (пакетный запрос) без должной подготовки среды часто приводит к сбоям.
Рассмотрим, как правильно подготовить запрос, чтобы избежать ошибок при передаче диапазона дат. Вместо использования переменных DECLARE, которые могут быть избыточны и вызывать ошибки при выполнении, мы будем использовать метод явного преобразования строки в тип datetime средствами самого SQL-сервера.
Для этого воспользуемся функцией CONVERT с указанием стиля 104 (это стандартный формат dd.mm.yyyy), что обеспечит гарантированное распознавание даты сервером.
Рассмотрим пошаговый пример реализации:
// Подготовка дат в 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. Это отключит вывод служебных сообщений, оставив только результат выборки, что сделает работу с базой данных значительно стабильнее.
При отладке подобных задач всегда следуйте этим советам:
ado.execute() падает, обязательно анализируйте коллекцию adocon.Errors. В ней содержится точный ответ сервера, например, о несоответствии типов или синтаксической ошибке.adocon.State. Соединение должно быть открыто, а адрес сервера — доступен.ADODB.Parameter. Это избавляет от необходимости вручную форматировать даты и защищает ваш запрос от SQL-инъекций. Драйвер базы данных самостоятельно приведет типы 1С к типам SQL, что исключает ошибки форматирования.Применяя данные подходы, вы сможете легко и безопасно получать данные из внешних SQL-источников, минимизируя риск возникновения ошибок при работе с датами и сложными структурами данных.