Интеграция 1С с внешними базами данных через технологию ADODB — это мощный инструмент, который, однако, таит в себе множество нюансов. Часто разработчики сталкиваются с ситуацией, когда запрос, написанный для одной СУБД (например, MS SQL), отказывается работать в другой (MySQL), или когда данные передаются некорректно. В этой статье мы подробно разберем, как избежать типичных ошибок при выполнении команды UPDATE, настроить кодировку и оптимизировать код для стабильной работы.
Проанализируем первую проблему, с которой столкнулся автор темы. В тексте ошибки фигурируют квадратные скобки: [Title]. Это классический синтаксис Microsoft SQL Server (T-SQL). Однако MySQL не понимает квадратные скобки для обозначения имен полей и таблиц.
Рассмотрим, как правильно оформлять идентификаторы в MySQL:
`Title`, если имя поля совпадает с зарезервированным словом SQL.Title.[] в MySQL всегда будут вызывать ошибку You have an error in your SQL syntax.Выясним причину ошибки в примере автора. Код [Title] = '"+Выборка.Наименование+"' должен быть заменен на Title = '"+Выборка.Наименование+"' или `Title` = '"+Выборка.Наименование+"'.
При передаче строковых данных из 1С (которая работает с Unicode) в MySQL через драйвер ODBC часто возникают проблемы с кириллицей. Если вместо русских букв в базу записывается «каша» из символов (например, Рстория), значит, драйвер и сервер не договорились о кодировке.
Посмотрим, как это исправить. Нам необходимо явно указать кодировку в строке подключения или сразу после открытия соединения. Разберем по шагам:
Вариант 1: Параметр в строке подключения
В объекте ConnectionString нужно добавить параметр CharSet. В зависимости от настроек вашей базы в MySQL это может быть utf8 или cp1251.
Соединение.ConnectionString = "DRIVER={MySQL ODBC 8.0 Unicode Driver};Server=" + СРВ + ";Database=" + БД + ";UID=" + УИД + ";PWD=" + ПВД + ";CharSet=utf8;";
Вариант 2: Выполнение команды установки имен
Сразу после метода Соединение.Open() выполните SQL-запрос, который установит кодировку текущего сеанса:
Соединение.Open();
Соединение.Execute("SET NAMES cp1251"); // Или utf8, в зависимости от кодировки таблиц
Разберем ситуацию, когда во все строки базы данных записываются значения только из последней строки выборки 1С. Это происходит из-за некорректного использования условия WHERE в запросе UPDATE.
Проанализируем код: если вы вызываете UPDATE Таблица SET Поле = 'Значение' без условия WHERE, СУБД обновит все записи в таблице. Если вы делаете это внутри цикла Пока Выборка.Следующий(), то каждая итерация будет перезаписывать всю таблицу данными текущего объекта 1С. В итоге, когда цикл закончится, в базе останутся только данные последней записи из выборки.
Правильный подход:
В каждом запросе обновления обязательно должен присутствовать уникальный идентификатор записи. Например:
Пока Выборка.Следующий() Цикл
ТекстЗапроса = "UPDATE Events_Types
|SET Title = '" + Выборка.Наименование + "'
|WHERE ID1C = '" + Выборка.ИдентификаторВнешнейБД + "'";
Соединение.Execute(ТекстЗапроса);
КонецЦикла;
Склеивание строк запроса вручную (через оператор +) считается плохим тоном («моветоном») и небезопасно. Рассмотрим причины:
Котлета 'Домашняя'), ваш SQL-запрос «развалится», так как кавычка внутри строки закроет строковый литерал раньше времени.1 500 превратится в строку "1 500", что вызовет синтаксическую ошибку в SQL.Истина в 1С нужно превращать в 1 для MySQL.Для решения этих проблем профессионалы используют объект ADODB.Command и параметры. Разберем, как это работает:
Команда = Новый COMОбъект("ADODB.Command");
Команда.ActiveConnection = Соединение;
// Используем знаки вопроса как заглушки для параметров
Команда.CommandText = "UPDATE Events_Types SET Title = ?, Publish = ? WHERE ID1C = ?";
Пока Выборка.Следующий() Цикл
Команда.Parameters.Refresh(); // Очистка или обновление коллекции
// Создаем параметры: Имя, Тип, Направление, Размер, Значение
// 202 - это adVarWChar (строка), 3 - adInteger (число)
Команда.Parameters.Append(Команда.CreateParameter("pTitle", 202, 1, 255, Выборка.Наименование));
Команда.Parameters.Append(Команда.CreateParameter("pPublish", 3, 1, , ?(Выборка.Публиковать, 1, 0)));
Команда.Parameters.Append(Команда.CreateParameter("pID", 3, 1, , Выборка.ID_В_SQL));
Команда.Execute();
КонецЦикла;
Если вам нужно обновить более 100-500 записей, выполнение Execute на каждой итерации цикла будет работать крайне медленно. Каждая команда — это отдельное обращение к серверу и фиксация данных на диске.
Посмотрим, как ускорить процесс в десятки раз с помощью транзакций. Мы просто «оборачиваем» наш цикл в команды начала и завершения транзакции:
Попытка
Соединение.Execute("START TRANSACTION;"); // Начинаем транзакцию
Пока Выборка.Следующий() Цикл
// Формируем и выполняем запросы здесь
Соединение.Execute(ТекстЗапроса);
КонецЦикла;
Соединение.Execute("COMMIT;"); // Фиксируем все изменения сразу
Сообщить("Данные успешно обновлены!");
Исключение
Соединение.Execute("ROLLBACK;"); // Отменяем всё, если произошла ошибка
Сообщить("Ошибка при обновлении: " + ОписаниеОшибки());
КонецПопытки;
Важно помнить, что в MySQL нет отдельного типа данных Boolean. Обычно используется TINYINT(1), где 0 — это Ложь, а 1 — Истина. При формировании запроса из 1С всегда делайте явное преобразование, как мы рассмотрели в примере с параметрами или через тернарный оператор: ?(Выборка.БулевоПоле, 1, 0).
Проанализировав все вышеперечисленные шаги, мы видим, что для успешного обновления записей необходимо: соблюдать синтаксис конкретной СУБД, следить за кодировкой соединения, всегда использовать фильтрацию по уникальному идентификатору и, в идеале, переходить на использование параметризованных запросов ADODB.Command. Это сделает ваш код надежным и защищенным от ошибок обработки строк.