Как правильно обновить записи в базе данных MySQL из 1С через ADODB?

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

Интеграция 1С с внешними базами данных через технологию ADODB — это мощный инструмент, который, однако, таит в себе множество нюансов. Часто разработчики сталкиваются с ситуацией, когда запрос, написанный для одной СУБД (например, MS SQL), отказывается работать в другой (MySQL), или когда данные передаются некорректно. В этой статье мы подробно разберем, как избежать типичных ошибок при выполнении команды UPDATE, настроить кодировку и оптимизировать код для стабильной работы.

Разбор синтаксических различий: MySQL против T-SQL

Проанализируем первую проблему, с которой столкнулся автор темы. В тексте ошибки фигурируют квадратные скобки: [Title]. Это классический синтаксис Microsoft SQL Server (T-SQL). Однако MySQL не понимает квадратные скобки для обозначения имен полей и таблиц.

Рассмотрим, как правильно оформлять идентификаторы в MySQL:

  1. Используйте обратные кавычки (backticks) — `Title`, если имя поля совпадает с зарезервированным словом SQL.
  2. Если имя поля уникально и не содержит пробелов, можно писать его вообще без кавычек: Title.
  3. Квадратные скобки [] в 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(ТекстЗапроса);
КонецЦикла;

Использование параметров через ADODB.Command

Склеивание строк запроса вручную (через оператор +) считается плохим тоном («моветоном») и небезопасно. Рассмотрим причины:

Для решения этих проблем профессионалы используют объект 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;"); // Отменяем всё, если произошла ошибка
    Сообщить("Ошибка при обновлении: " + ОписаниеОшибки());
КонецПопытки;

Особенности типа Boolean в MySQL

Важно помнить, что в MySQL нет отдельного типа данных Boolean. Обычно используется TINYINT(1), где 0 — это Ложь, а 1 — Истина. При формировании запроса из 1С всегда делайте явное преобразование, как мы рассмотрели в примере с параметрами или через тернарный оператор: ?(Выборка.БулевоПоле, 1, 0).

Проанализировав все вышеперечисленные шаги, мы видим, что для успешного обновления записей необходимо: соблюдать синтаксис конкретной СУБД, следить за кодировкой соединения, всегда использовать фильтрацию по уникальному идентификатору и, в идеале, переходить на использование параметризованных запросов ADODB.Command. Это сделает ваш код надежным и защищенным от ошибок обработки строк.

← На главную