Как исправить ошибку ODBC 1064 при записи данных из 1С в MySQL через внешний источник данных?

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

При интеграции платформы 1С:Предприятие с внешними базами данных под управлением MySQL разработчики часто сталкиваются с непредвиденным поведением драйверов ODBC. Одной из наиболее распространенных проблем является синтаксическая ошибка СУБД, сопровождающаяся кодом SQLSTATE: 42000 Номер ошибки: 1064. В этой статье мы подробно разберем, почему возникает эта ошибка, как настроить корректное экранирование зарезервированных имен СУБД, в чем разница между объектной и необъектной моделями записи в 1С, и как обойти ограничения контекста компиляции на мобильном сервере.

Разбор причин ошибки 1064 (SQLSTATE: 42000) при интеграции 1С и MySQL

Для того чтобы понять природу этой ошибки, проанализируем фрагмент текста ошибки СУБД, полученный из логов драйвера:

You have an error in your SQL syntax; check the manual... near 'group,gr) VALUES('йййй','0'...

Выясним причину этого сбоя. В данном сценарии проблема кроется в именах таблиц и полей, которые мы пытаемся записать. Обратим внимание на поля group и date. В СУБД MySQL оба эти слова являются зарезервированными ключевыми словами. Слово GROUP зарезервировано для операций группировки в синтаксисе GROUP BY, а DATE — для системных типов данных и встроенных функций работы с датами.

Когда платформа 1С генерирует автоматический SQL-запрос на запись во внешнюю таблицу СУБД (например, при вызове метода Записать()), она ориентируется на стандарты ANSI SQL. По этим стандартам все идентификаторы (названия таблиц и колонок) должны экранироваться двойными кавычками ("group", "date"). Однако в MySQL по умолчанию приняты совершенно другие правила экранирования — там используются обратные апострофы, или бэктэки (`group`, `date`). Двойные же кавычки СУБД MySQL воспринимает как строковые литералы (обычный текст).

Поскольку ODBC-драйвер отправляет запрос «как есть», парсер MySQL спотыкается на слове group, не понимая, что это имя колонки, и считает его синтаксической ошибкой оператора INSERT.

Решение проблемы экранирования без изменения структуры базы данных MySQL

Рассмотрим, как заставить MySQL понимать стандартные кавычки ANSI SQL, генерируемые платформой 1С. Для этого существует специальный режим работы SQL-сервера под названием ANSI_QUOTES. Если этот режим включен, MySQL начинает воспринимать двойные кавычки как ограничители идентификаторов объектов (таблиц и полей), точно так же, как это делают Microsoft SQL Server или PostgreSQL.

Активировать данный режим можно непосредственно при инициализации сессии ODBC-подключения из 1С. Разберем по шагам, как это сделать:

  1. Откроем свойства внешнего источника данных в конфигураторе 1С.
  2. Перейдем к параметрам строки соединения.
  3. В строку инициализации подключения добавим специальный параметр драйвера INITSTMT (или STMT в зависимости от версии ODBC-драйвера).

Пример строки подключения для СУБД MySQL с активированным режимом совместимости кавычек:


Driver={MySQL ODBC 5.1 Driver};Server=my_server_address;Database=my_db;Uid=my_user;Pwd=my_password;INITSTMT=SET sql_mode='ANSI_QUOTES';

Если мы используем более современный ODBC-драйвер, например, версии 8.0, строка будет выглядеть аналогично:


Driver={MySQL ODBC 8.0 Unicode Driver};Server=my_server_address;Database=my_db;Uid=my_user;Pwd=my_password;STMT=SET sql_mode='ANSI_QUOTES';

При таком подходе СУБД MySQL корректно обработает кавычки, и синтаксическая ошибка 1064 будет полностью устранена без необходимости переименовывать таблицы и колонки в работающей внешней базе данных.

Запись во внешние источники: Объектная модель против Менеджера записи

Проанализируем архитектурные подходы работы с внешними таблицами из 1С. В сообщениях форума упоминается дилемма между использованием Объектной модели и Менеджера записи. Разберем, в чем разница и как правильно писать код.

Вариант 1. Объектная модель (СоздатьОбъект)

Этот метод отлично подходит, если в 1С для внешней таблицы настроено сопоставление с объектной сущностью (аналог Справочника). У таблицы обязательно должен быть определен уникальный ключ идентификации (Primary Key). Посмотрим на пример кода, который использовал автор темы:


мХарактеристика = ВнешниеИсточникиДанных.Сайт.Таблицы.date.СоздатьОбъект();
мХарактеристика.Price = 0;
мХарактеристика.Name = В.Name;
мХарактеристика.id = В.id;
мХарактеристика.gr = В.gr;
мХарактеристика.dt = В.dt;
мХарактеристика.Записать();

При вызове метода Записать() для нового объекта платформа 1С пытается автоматически определить автоинкрементное ключевое поле (Primary Key) в СУБД и выполнить системную функцию получения последнего сгенерированного ID, вызывая LAST_INSERT_ID(). Если в метаданных внешнего источника данных 1С это поле сопоставлено некорректно (например, не стоит признак автозаполнения на стороне СУБД), то при попытке записать строку вручную платформа может сломать логику генерации ключей, что также приведет к ошибке.

Вариант 2. Необъектная модель (СоздатьМенеджерЗаписи)

Если таблица в MySQL представляет собой плоский список без выделенного уникального объектного идентификатора (например, это таблица логов или аналог Регистра сведений в 1С), объектная модель работать не будет. В таких случаях мы должны использовать Менеджер записи. Посмотрим, как выглядит правильная модификация записи через этот механизм:


МенеджерЗаписи = ВнешниеИсточникиДанных.Сайт.Таблицы.date.СоздатьМенеджерЗаписи();
// Обязательно заполняем ключевые поля для поиска/позиционирования записи
МенеджерЗаписи.id = В.id; 
МенеджерЗаписи.Прочитать(); // Считываем текущие данные из БД

// Модифицируем необходимые поля
МенеджерЗаписи.Price = 0;
МенеджерЗаписи.Name = В.Name;
МенеджерЗаписи.gr = В.gr;
МенеджерЗаписи.dt = В.dt;

// Записываем изменения в СУБД
МенеджерЗаписи.Записать();

Использование менеджера записи гарантирует более прогнозируемое поведение платформы при работе со стандартными плоскими таблицами баз данных.

Как перехватить и проанализировать «сырые» SQL-запросы от 1С к MySQL

Для быстрой диагностики проблем интеграции нам необходимо точно знать, какой именно SQL-запрос формирует платформа 1С перед отправкой через ODBC-драйвер. Рассмотрим три основных метода мониторинга запросов.

Способ 1. Использование Технологического журнала (ТЖ) 1С

Это самый точный способ отладки со стороны платформы 1С. Нам необходимо настроить конфигурационный файл logcfg.xml на сервере приложений 1С. За логирование работы с ODBC отвечает системное событие DBODBC. Создадим файл конфигурации следующего содержания:


<config xmlns="http://v8.1c.ru/8.1/xdto">
    <log location="C:\1C_logs\ODBC" history="24">
        <event>
            <eq property="Name" value="DBODBC"/>
        </event>
        <property name="All"/>
    </log>
</config>

После сохранения файла в каталоге C:\1C_logs\ODBC начнут создаваться текстовые файлы логов, где мы сможем в реальном времени наблюдать все подготовленные и выполненные SQL-запросы с переданными параметрами.

Способ 2. Логирование на стороне MySQL (General Query Log)

Если у нас есть права администратора на сервере MySQL, мы можем временно включить журналирование всех входящих запросов напрямую в базу данных. Для этого выполним в консоли MySQL следующие команды:


SET GLOBAL general_log = 'ON';
SET GLOBAL log_output = 'TABLE';

После выполнения операции записи в 1С мы сможем проанализировать пришедшие SQL-инструкции, сделав выборку из системной таблицы логирования:

SELECT * FROM mysql.general_log ORDER BY event_time DESC;

Не забудьте отключить логирование после завершения отладки, чтобы не снижать общую производительность СУБД:

SET GLOBAL general_log = 'OFF';

Ограничения контекста исполнения кода внешних источников данных

Разберем ошибку компиляции, упомянутую в Сообщении 5:

Переменная не определена (ВнешниеИсточникиДанных) (Проверка: Мобильное приложение-сервер)

Выясним причину этого сбоя. Объект метаданных ВнешниеИсточникиДанных относится к платформенным механизмам интеграции корпоративного уровня. Согласно официальной документации 1С, данный глобальный контекст имеет жесткие ограничения по доступности среды выполнения:

Если в настройках конфигурации включена проверка кода для мобильных платформ, компилятор выдаст ошибку при первой же попытке обратиться к ВнешниеИсточникиДанных в общем модуле или модуле формы.

Для исправления этой ошибки мы должны изолировать серверный код работы с внешними базами данных с помощью директив препроцессора. Код должен выполняться только на стандартном «большом» сервере 1С. Обернем наш код в следующую конструкцию:


#Если Сервер И Не МобильноеПриложениеСервер И Не МобильноеПриложениеКлиент Тогда
    мХарактеристика = ВнешниеИсточникиДанных.Сайт.Таблицы.date.СоздатьОбъект();
    // Код работы с базой данных MySQL
#КонецЕсли

Это исключит проверку данного блока кода при компиляции для мобильных устройств, и синтаксическая ошибка компилятора исчезнет.

Настройка кодировок и выбор правильного драйвера ODBC

При передаче строковых данных на русском языке (например, строкового значения 'йййй' из Сообщения 1) крайне важно уделить внимание выбору правильного ODBC-драйвера.

Драйверы MySQL ODBC поставляются в двух различных редакциях:

Для корректной работы с русскими символами (кириллицей) из 1С необходимо использовать исключительно Unicode-версию драйвера. При использовании ANSI-драйвера русские буквы будут искажены, превращены в знаки вопроса (???), либо СУБД вернет ошибку некорректной кодировки при попытке записи.

Также важно помнить о разрядности программного обеспечения: если служба сервера приложений 1С:Предприятие работает в 64-битном режиме (что является стандартом для современных систем), то на сервере обязательно должен быть установлен именно 64-битный ODBC-драйвер СУБД MySQL. Настройка источника данных (DSN) при этом должна производиться через 64-битную версию утилиты администрирования ODBC в Windows (расположенную по пути C:\Windows\System32\odbcad32.exe).

← На главную