При разработке интеграций между 1С и внешними интернет-магазинами (например, OpenCart) программисты часто обращаются к базе данных MySQL напрямую через технологию COM-соединения ADODB.Connection и системный ODBC-драйвер. Нередко возникает ситуация, когда простые запросы на чтение данных отрабатывают корректно, однако при попытке выполнить пакет из нескольких команд (содержащий установку переменных сессии, транзакции и несколько операторов INSERT или UPDATE) платформа выдает ошибку:
[MySQL][ODBC Driver][mysqld] You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near...
При этом тот же самый SQL-скрипт без ошибок выполняется в консоли phpMyAdmin. Разберем детально причины такого поведения и рассмотрим надежные способы решения этой задачи.
Проанализируем техническую сторону взаимодействия 1С, драйвера ODBC и СУБД MySQL:
Execute. СУБД успешно считывает первую инструкцию (например, SET SQL_MODE = ...;), а последующий текст начинает интерпретировать как некорректное продолжение первой команды, что и вызывает синтаксическую ошибку.Наиболее надежный и правильный подход при работе с базой через COM-объект — отказаться от склеивания команд в одну большую строку. Вместо явной передачи команд START TRANSACTION, COMMIT или ROLLBACK в тексте SQL-запроса следует использовать встроенные методы объекта ADODB.Connection.
Рассмотрим пример правильной организации пакетной записи данных в 1С:
Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.ConnectionString = "DRIVER={MySQL ODBC 5.3 Unicode Driver};SERVER=localhost;DATABASE=shop_db;UID=root;PWD=password;OPTION=3;";
Соединение.Open();
// Открываем транзакцию средствами ADO
Соединение.BeginTrans();
Попытка
// Выполняем установку параметров сессии отдельной командой
Соединение.Execute("SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO'");
Соединение.Execute("SET time_zone = '+00:00'");
// Выполняем первую вставку данных
ТекстЗапросаКатегории =
"INSERT INTO `do_category` (`category_id`, `image`, `parent_id`, `top`, `column`, `sort_order`, `status`, `date_added`, `date_modified`) " +
"VALUES (2, 'catalog/Tovar/Samokat2.jpg', 0, 0, 1, 0, 1, '2023-01-01 00:00:00', '2023-01-01 00:00:00') " +
"ON DUPLICATE KEY UPDATE `image` = VALUES(`image`), `parent_id` = VALUES(`parent_id`)";
Соединение.Execute(ТекстЗапросаКатегории);
// Выполняем вторую вставку данных
ТекстЗапросаОписания =
"INSERT INTO `do_category_description` (`category_id`, `language_id`, `name`, `description`, `meta_title`, `meta_description`, `meta_keyword`) " +
"VALUES (2, 1, 'Конструкторы', '', 'Конструкторы', 'Конструкторы', 'Конструкторы') " +
"ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `description` = VALUES(`description`)";
Соединение.Execute(ТекстЗапросаОписания);
// Фиксируем транзакцию, если все команды завершились успешно
Соединение.CommitTrans();
Исключение
// В случае ошибки отменяем все изменения
Соединение.RollbackTrans();
Соединение.Close();
ВызватьИсключение "Ошибка при записи данных в MySQL: " + ОписаниеОшибки();
КонецПопытки;
Соединение.Close();
Такой подход гарантирует атомарность всей пачки данных: если хотя бы один из запросов завершится ошибкой, метод RollbackTrans() откатит состояние таблиц к исходному.
Если специфика алгоритма требует отправки готового монолитного SQL-скрипта (дампа), можно принудительно включить поддержку пакетных выражений на уровне драйвера. Для этого в строку подключения добавляется специальный флаг:
Добавьте в строку подключения параметр CLIENT_MULTI_STATEMENTS=1 или числовой флаг FLAG_MULTI_STATEMENTS в параметре OPTION (комбинация битовых флагов OPTION=67108864).
Соединение = Новый COMОбъект("ADODB.Connection");
СтрокаПодключения = "DRIVER={MySQL ODBC 5.3 Unicode Driver};SERVER=localhost;DATABASE=shop_db;UID=root;PWD=password;CLIENT_MULTI_STATEMENTS=1;";
Соединение.Open(СтрокаПодключения);
Соединение.Execute(ТекстСоставногоЗапроса);
Соединение.Close();
Обратите внимание: этот вариант снижает уровень защищенности базы данных и требует явной поддержки флага со стороны версии сервера MySQL.
Прямое подключение к СУБД сайта через внешнюю сеть (порт 3306) несет риски безопасности и часто блокируется хостинг-провайдерами. Альтернативный вариант — взаимодействие через HTTP-запросы.
Посмотрим на пример отправки данных из 1С на серверный скрипт:
HTTPСоединение = Новый HTTPСоединение("mysite.ru", 443, , , , 30, Новый ЗащищенноеСоединениеOpenSSL());
HTTPЗапрос = Новый HTTPЗапрос("/api/sync_categories.php");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.Заголовки.Вставить("Authorization", "Bearer СекретныйТокенАвторизации");
// Формируем тело запроса (например, в формате JSON)
ТекстJSON = "{""category_id"": 2, ""name"": ""Конструкторы"", ""parent_id"": 0}";
HTTPЗапрос.УстановитьТелоИзСтроки(ТекстJSON, КодировкаТекста.UTF8);
Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
Если Ответ.КодСостояния <> 200 Тогда
ВызватьИсключение "Ошибка отправки данных: " + Ответ.ПолучитьТелоКакСтроку();
КонецЕсли;
Важно: при использовании промежуточных веб-скриптов обязательно реализуйте авторизацию по токену и валидацию входящих параметров для защиты от несанкционированного доступа.
Если обмен данными строится внутри корпоративной сети и требуется регулярная работа с таблицами MySQL, обратите внимание на следующие механизмы: