При работе с базами данных SQLite в среде 1С:Предприятие 7.7 разработчики часто используют внешнюю компоненту 1sqlite.dll. Она позволяет существенно расширить возможности системы, быстро обрабатывать большие объемы информации локально и строить сложные выборки. Однако на практике можно столкнуться с неприятной ситуацией: простой запрос на добавление данных INSERT INTO, который успешно выполняется во внешних редакторах (например, в SQLiteStudio), внутри кода 1С отрабатывает без видимых ошибок, но данные в таблице не появляются, либо система аварийно завершает работу.
В этой статье мы подробно разберем, почему может не выполняться запрос вставки данных через 1sqlite.dll, и рассмотрим пошаговые методы устранения этой проблемы.
Самая распространенная ошибка разработчиков при работе с внешними компонентами — «слепое» подавление исключений. В исходном коде автора темы в блоке обработки ошибок выводится стандартное текстовое сообщение:
Попытка
Запрос = БазаДанных.НовыйЗапрос();
Запрос.ВыполнитьЗапрос("INSERT INTO tab(n1,n2,n3) VALUES(1,2,3)");
Исключение
БазаДанных.Закрыть();
Сообщить("Не удалось выполнить запрос.", "!");
КонецПопытки;
При таком подходе истинная причина падения остается загадкой. Первое, что мы должны сделать — заставить систему показать нам системное описание ошибки. Для этого обязательно используем встроенную функцию ОписаниеОшибки(). Перепишем блок следующим образом:
Попытка
Запрос = БазаДанных.НовыйЗапрос();
Запрос.ВыполнитьЗапрос("INSERT INTO tab(n1,n2,n3) VALUES(1,2,3)");
Исключение
Сообщить(ОписаниеОшибки(), "!");
БазаДанных.Закрыть();
КонецПопытки;
Теперь, если запрос завершится неудачей, в табло 1С будет выведена конкретная причина ошибки, например: no such table (нет такой таблицы), database is locked (база данных заблокирована) или near "VALUES": syntax error (синтаксическая ошибка).
Обратите внимание на путь к файлу базы данных в коде: БазаДанных.Открыть("C:\test.db");. Если вы работаете в современных операционных системах (Windows 7, 10, 11) с включенным контролем учетных записей (UAC), запись файлов напрямую в корень диска C:\ без прав администратора запрещена.
Проанализируем, что происходит в этот момент:
%localappdata%\VirtualStore\test.db.tab.C:\test.db, где таблица уже создана вами вручную.Решение: Никогда не храните файлы баз данных в корне системного диска. Перенесите базу данных в каталог, гарантированно открытый для чтения и записи текущему пользователю. Оптимальным решением будет использование каталога базы данных 1С или временной папки:
ПутьКБД = КаталогИБ() + "sqlite_data.db";
БазаДанных.Открыть(ПутьКБД);
SQLite — это встраиваемая база данных, ориентированная на однопользовательскую запись. Если в процессе отладки кода в 1С у вас параллельно открыта программа SQLiteStudio, в которой вы просматриваете структуру или редактируете данные, она может монопольно заблокировать файл базы данных.
При попытке выполнить INSERT из 1С движок базы данных мгновенно вернет ошибку блокировки. Чтобы решить эту проблему, выполните следующие действия:
БазаДанных.Открыть(ПутьКБД);
БазаДанных.ВыполнитьЗапрос("PRAGMA journal_mode = WAL;");
В SQLite по умолчанию действует режим автофиксации транзакций (Auto-commit mode). Это значит, что любая одиночная инструкция INSERT, UPDATE или DELETE автоматически оборачивается в транзакцию и сразу же сохраняется на диске. Делать ручной COMMIT для одной строки не требуется.
Однако, если в вашем коде выше по тексту была открыта явная транзакция командой BEGIN TRANSACTION, изменения не будут физически записаны в файл до тех пор, пока вы явно не вызовете команду фиксации. Рассмотрим правильную структуру работы с групповой вставкой данных:
Попытка
БазаДанных.ВыполнитьЗапрос("BEGIN TRANSACTION;");
// Выполняем серию вставок в цикле
Для Инд = 1 По 10 Цикл
Запрос = БазаДанных.НовыйЗапрос();
// Формируем и выполняем запросы
Запрос.ВыполнитьЗапрос("INSERT INTO tab(n1,n2,n3) VALUES(" + Инд + ", 2, 3)");
КонецЦикла;
// Фиксируем все изменения на диске за один шаг
БазаДанных.ВыполнитьЗапрос("COMMIT;");
Исключение
// В случае ошибки обязательно откатываем транзакцию
БазаДанных.ВыполнитьЗапрос("ROLLBACK;");
Сообщить(ОписаниеОшибки(), "!");
БазаДанных.Закрыть();
КонецПопытки;
Использование транзакций при вставке нескольких строк ускоряет работу SQLite в сотни раз, так как запись на жесткий диск происходит один раз вместо постоянного обращения к файловой системе на каждую строчку.
Если вы пытаетесь выполнить вставку сразу нескольких строк одним запросом (множественный INSERT), синтаксис вашего запроса может выглядеть так:
INSERT INTO tab(n1,n2,n3) VALUES (1,2,3), (4,5,6), (7,8,9);
Выясним важную техническую деталь: оригинальная и наиболее распространенная версия компоненты 1sqlite.dll от Александра Орефкова (версия 1.0.2.6) базируется на устаревшем движке SQLite версии 3.7.10. В этой версии синтаксис вставки нескольких строк через запятую еще не поддерживался (он появился только в версии 3.7.11).
Если вы столкнулись с синтаксической ошибкой при попытке групповой вставки, у вас есть два пути решения:
1sqlite.dll на более современную сборку (например, форки от сторонних разработчиков сообщества 1С, где версия движка SQLite обновлена до актуальных версий 3.30+).Если вы передаете в запрос текстовые данные из справочников или документов 1С, вы можете столкнуться с ошибкой синтаксиса, если в строке встретится символ одинарной кавычки (апостроф '). Например, название организации ООО 'Рога и Копыта' нарушит структуру SQL-запроса.
Чтобы избежать подобных уязвимостей и синтаксических сбоев, рекомендуется экранировать текстовые параметры (дублировать кавычки) или использовать параметризованные запросы, которые поддерживает компонента 1sqlite:
// Пример безопасной вставки через подготовку запроса с параметрами
Запрос = БазаДанных.НовыйЗапрос();
Запрос.Подготовить("INSERT INTO tab(n1, n2, n3) VALUES (:Парам1, :Парам2, :Парам3)");
Запрос.УстановитьПараметр("Парам1", Значение1);
Запрос.УстановитьПараметр("Парам2", Значение2);
Запрос.УстановитьПараметр("Парам3", Значение3);
Запрос.ВыполнитьЗапрос();
Использование параметризованных запросов полностью исключает ошибки, связанные с типами данных и спецсимволами, а также повышает безопасность и скорость выполнения операций.