При работе с внешними источниками данных (ВИД) в системе 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда стандартные методы объектной модели, такие как НайтиПоПолю(), получение объекта и последующий вызов метода Удалить(), приводят к критической ошибке. Текст ошибки обычно ссылается на внутренние файлы ядра платформы: «Недопустимое состояние объекта [backend - src\backend\src\SdblMySQL.h (64)]». Эта проблема особенно актуальна для СУБД MySQL и MariaDB.
В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем ограничения платформы при работе с ODBC-драйверами и рассмотрим несколько эффективных способов решения задачи удаления записей.
Давайте проанализируем ситуацию с точки зрения взаимодействия компонентов. Когда мы вызываем метод Удалить() для объекта внешнего источника, платформа 1С пытается транслировать это действие во внутренний язык запросов SDBL (Simple Data Bank Language), который, в свою очередь, должен сгенерировать SQL-команду DELETE для конкретной СУБД.
Основная причина сбоя кроется в том, как драйвер ODBC передает метаданные о таблице платформе 1С. Если таблица имеет составной первичный ключ (состоит из двух и более колонок) или если драйвер сообщает о ключевых полях в формате, который 1С интерпретирует как неоднозначный, генерация запроса блокируется на уровне ядра. В итоге платформа «теряет» состояние объекта и выдает ошибку в модуле SdblMySQL.h еще до того, как запрос будет отправлен в сторону MySQL.
Рассмотрим пошагово способы обхода этого ограничения.
Самый простой и эффективный способ, который не требует изменения структуры сторонней базы данных, — это выполнение прямой SQL-команды. Механизм внешних источников данных позволяет отправлять запросы в «родном» синтаксисе СУБД, минуя транслятор SDBL и объектную модель 1С.
Разберем пример кода для удаления записи по идентификатору:
// Определяем текст запроса на языке MySQL
ТекстЗапроса = "DELETE FROM my_table WHERE id_field = " + Формат(ИдентификаторДляУдаления, "ЧГ=0");
// Выполняем команду напрямую через внешний источник данных
Попытка
ВнешниеИсточникиДанных.ИмяВашегоИсточника.ВыполнитьКоманду(ТекстЗапроса);
Сообщить("Запись успешно удалена");
Исключение
Сообщить("Ошибка при удалении: " + ОписаниеОшибки());
КонецПопытки;
Этот метод универсален, так как он полностью игнорирует настройки объектных данных в конфигураторе и позволяет работать с таблицами любой сложности, включая те, где используются составные ключи.
Если логика удаления требует дополнительных проверок на стороне СУБД или если вы хотите инкапсулировать SQL-код внутри базы данных, отличным решением станет использование хранимых процедур. Это позволяет избежать передачи сложных строк запросов из 1С.
Для начала создадим процедуру в MySQL (например, через phpMyAdmin или MySQL Workbench):
DELIMITER //
CREATE PROCEDURE DeleteRecordByID(IN p_id INT)
BEGIN
DELETE FROM table1 WHERE Id = p_id;
END //
DELIMITER ;
После этого в 1С достаточно вызвать эту процедуру через тот же метод ВыполнитьКоманду:
Идентификатор = 123;
ТекстКоманды = "CALL DeleteRecordByID(" + Формат(Идентификатор, "ЧГ=0") + ")";
ВнешниеИсточникиДанных.ИмяВашегоИсточника.ВыполнитьКоманду(ТекстКоманды);
Важный нюанс: при использовании этого метода убедитесь, что у пользователя, под которым 1С подключается к MySQL, достаточно прав на выполнение (EXECUTE) хранимых процедур.
В наиболее сложных случаях, когда штатный механизм ВИД работает нестабильно или не позволяет гибко управлять транзакциями, можно использовать COM-объект ADODB.Connection. Это «промышленный» стандарт для интеграции, который работает в обход механизмов платформы 1С, предназначенных для внешних источников.
Посмотрим на пример реализации:
Connection = Новый COMОбъект("ADODB.Connection");
// Строка соединения может использовать DSN или прямое описание драйвера
ConnectionString = "Driver={MySQL ODBC 8.0 Unicode Driver};Server=my_server;Database=my_db;User=my_user;Password=my_pass;Option=3;";
Попытка
Connection.Open(ConnectionString);
SQL = "DELETE FROM table1 WHERE key_part1 = 10 AND key_part2 = 20";
Connection.Execute(SQL);
Connection.Close();
Сообщить("Удаление через ADO выполнено");
Исключение
Сообщить("Ошибка ADO: " + ОписаниеОшибки());
КонецПопытки;
Иногда проблему можно нивелировать правильным подбором версии драйвера и его параметров. Проанализируем основные моменты:
SdblMySQL.h, попробуйте установить MySQL ODBC 5.3 Unicode Driver. Он считается наиболее стабильным для работы с 1С.НаборЗаписей, хотя, как показывает практика, для удаления это не всегда спасает от вышеуказанной ошибки.Выясним причину окончательно: ошибка ядра SdblMySQL.h (64) — это следствие несовместимости транслятора 1С и специфических ответов ODBC-драйвера MySQL при попытке использования объектной модели (Удалить()).
Для надежной работы рекомендуем придерживаться следующей стратегии:
ВнешниеИсточникиДанных.Имя.ВыполнитьКоманду() для простых операций удаления.ADODB.Connection, если требуется полный контроль над соединением и специфическими типами данных СУБД.Соблюдение этих рекомендаций позволит вам избежать «падения» платформы и обеспечит стабильную работу интеграционных механизмов вашей системы.