Работа с внешними базами данных часто становится необходимостью, когда нужно интегрировать 1С с мобильными приложениями, веб-сервисами или локальными кэшами. SQLite является одной из самых популярных встраиваемых СУБД, однако при попытке записать в неё двоичные данные (например, изображения формата JPG или PNG) напрямую через SQL-запрос типа INSERT, разработчики сталкиваются с трудностями. В этой статье мы подробно разберем, как правильно передать файл в поле типа BLOB, используя механизмы ADO, и как избежать проблем с кодировкой кириллических символов.
Рассмотрим стандартную ситуацию: у нас есть путь к файлу картинки, и мы хотим добавить её в таблицу. На первый взгляд кажется, что достаточно сформировать строку запроса. Однако двоичные данные содержат спецсимволы, которые нарушат структуру SQL-команды. Кроме того, 1С не может просто «склеить» объект ДвоичныеДанные со строкой запроса. Для решения этой задачи мы будем использовать параметризацию запросов через объект ADODB.Command и вспомогательный объект ADODB.Stream для чтения файла.
Для начала проанализируем процесс подключения. Нам потребуется установленный в системе SQLite ODBC Driver. Мы создаем объект соединения и открываем его, указывая путь к файлу базы данных. Рекомендуется использовать параметры, оптимизирующие скорость записи, так как SQLite блокирует базу при выполнении транзакций.
// Установим соединение
ФайлБД = "C:\Data\my_database.db";
SQLiteObject = Новый COMОбъект("ADODB.Connection");
// В строке подключения можно добавить SyncPragma=NORMAL для ускорения
SQLiteConnectionString = "DRIVER=SQLite3 ODBC Driver;Database=" + ФайлБД + ";";
SQLiteObject.Open(SQLiteConnectionString);
Чтобы передать бинарный файл, нам нужно отказаться от прямой сборки строки запроса и перейти к использованию параметров (символы ? в тексте запроса). Это не только позволяет передавать BLOB, но и защищает от SQL-инъекций. Разберем создание команды:
cmd = Новый COMОбъект("ADODB.Command");
cmd.ActiveConnection = SQLiteObject;
// Используем знаки вопроса как заполнители для параметров
cmd.CommandText = "INSERT INTO Goods (_id, _name, _text, _jpg) VALUES (?, ?, ?, ?)";
cmd.CommandType = 1; // adCmdText
Поскольку 1С передает данные в COM-объекты в своем специфическом формате, напрямую передать объект ДвоичныеДанные в параметр ADO не получится — это вызовет ошибку несоответствия типов. Нам поможет ADODB.Stream, который прочитает файл в массив байтов, понятный драйверу ODBC.
Проанализируем процедуру подготовки бинарных данных:
ПутьКФайлу = "C:\Images\item_001.jpg";
ФайлКартинки = Новый Файл(ПутьКФайлу);
Если ФайлКартинки.Существует() Тогда
StreamIn = Новый COMОбъект("ADODB.Stream");
StreamIn.Type = 1; // adTypeBinary (двоичные данные)
StreamIn.Open();
StreamIn.LoadFromFile(ПутьКФайлу);
// Читаем всё содержимое в переменную
БинарныеДанные = StreamIn.Read();
РазмерФайла = StreamIn.Size;
StreamIn.Close();
Иначе
БинарныеДанные = Неопределено;
РазмерФайла = 0;
КонецЕсли;
Теперь самое важное — правильно типизировать параметры. Выясним причину частой ошибки «Аргументы имеют неверный тип». Она возникает, если константы типов ADO указаны неверно. Рассмотрим основные типы:
202 (adVarWChar) — для строк Unicode (кириллица).205 (adLongVarBinary) — для больших двоичных данных (BLOB).Приступим к сборке и выполнению:
// Очистим параметры, если команда используется в цикле
cmd.Parameters.Refresh();
// Добавляем строковые параметры (ID и Наименование)
// Используем 202 тип (adVarWChar) для корректной передачи кириллицы
cmd.Parameters.Append(cmd.CreateParameter("@Id", 202, 1, 100, СокрЛП(Выборка.ID)));
cmd.Parameters.Append(cmd.CreateParameter("@Name", 202, 1, 255, СокрЛП(Выборка.Наименование)));
cmd.Parameters.Append(cmd.CreateParameter("@Text", 202, 1, 1000, СокрЛП(Выборка.Описание)));
// Добавляем параметр BLOB
Если БинарныеДанные <> Неопределено Тогда
// Тип 205 - adLongVarBinary, 1 - adParamInput
cmd.Parameters.Append(cmd.CreateParameter("@Jpg", 205, 1, РазмерФайла, БинарныеДанные));
Иначе
// Если картинки нет, передаем NULL (тип 205 с размером 0 или специальный Null)
cmd.Parameters.Append(cmd.CreateParameter("@Jpg", 205, 1, 1, Неопределено));
КонецЕсли;
cmd.Execute();
Важный момент: если объем файла очень большой, вместо прямой передачи Value можно использовать метод AppendChunk. Это позволит передавать данные порциями, минимизируя нагрузку на память.
Многие разработчики замечают, что при записи кириллических строк в SQLite через ADO, данные в базе отображаются как BLOB или некорректные символы. Выясним причину: SQLite по умолчанию ожидает UTF-8. Если в методе CreateParameter вы используете тип 200 (adVarChar), драйвер пытается передать строку в ANSI-кодировке. Если она не соответствует системной локали или содержит специфические символы, SQLite может интерпретировать входящий поток байтов как бинарный.
Решение: Всегда используйте тип 202 (adVarWChar). Это заставляет ADO передавать данные в формате WideChar (Unicode), который корректно обрабатывается современными ODBC-драйверами SQLite и правильно преобразуется в UTF-8 внутри базы.
Если ваша конфигурация работает на платформе 8.3.x, стоит рассмотреть использование механизма «Внешние источники данных». Это значительно упрощает работу:
ХранилищеЗначения.ADODB.Stream или Command.НоваяСтрока.ПолеКартинки = Новый ХранилищеЗначения(ДвоичныеДанные);.Этот способ является более «нативным» для 1С и рекомендуется для новых разработок, так как он платформенно независим и работает в том числе на Linux-серверах (при наличии соответствующего драйвера).
Мы рассмотрели детальный алгоритм записи изображений в SQLite. Подытожим основные правила: используйте ADODB.Command для безопасности и работы с параметрами, применяйте ADODB.Stream для корректного чтения бинарных файлов и не забывайте про Unicode-типы параметров (202) для текстовых полей, чтобы избежать проблем с кириллицей. Такой подход обеспечит стабильную работу интеграции и целостность ваших данных.