При работе с внешними базами данных, такими как SQLite, из 1С 7.7 часто возникает задача создания временных таблиц для промежуточных расчетов. В многопользовательской среде это порождает проблему: как назвать таблицу так, чтобы избежать конфликтов, когда несколько пользователей одновременно выполняют одну и ту же операцию? Простое, статичное имя вроде "vt_temp_data" неминуемо приведет к ошибкам.
Рассмотрим несколько подходов к генерации уникального имени для временной таблицы, а также разберем лучший, нативный способ работы с временными данными в SQLite, который полностью избавляет от этой проблемы.
Основная причина — избежание коллизий. Если два процесса попытаются одновременно создать или записать данные в таблицу с одинаковым именем в общей базе данных, возникнет ошибка или данные одного процесса перезапишут данные другого. Кроме того, при генерации имени важно учитывать технические ограничения самой СУБД SQLite.
_. Использование других символов, например дефиса -, недопустимо и вызовет ошибку SQL. Если все же необходимо использовать спецсимволы, имя нужно заключать в двойные кавычки, но лучше этого избегать.Теперь проанализируем, как можно сгенерировать подходящее имя средствами 1С 7.7.
Это самый надежный способ обеспечить уникальность. GUID — это 128-битное число, вероятность повторения которого ничтожно мала. Получить его в 1С 7.7 можно несколькими путями.
Вариант с компонентой 1C++
Если у вас установлена компонента 1C++, можно использовать объект "GUID". Однако, как мы выяснили, стандартное строковое представление GUID содержит дефисы, которые недопустимы в именах таблиц SQLite. Их необходимо удалить.
Посмотрим на пример кода, который решает эту проблему:
// Создаем объект для работы с GUID (требуется ВК 1C++)
лGUID = СоздатьОбъект("GUID");
лGUID.Новый();
// Получаем строковое представление GUID, например: "{bb1a46b7-65e7-4824-8c74-640b2741d4df}"
лGUID_Строка = лGUID.ВСтроку();
// Удаляем недопустимые символы - дефисы
лGUID_Строка = СтрЗаменить(лGUID_Строка, "-", "");
// Также можно убрать и фигурные скобки, если они есть
лGUID_Строка = СтрЗаменить(лGUID_Строка, "{", "");
лGUID_Строка = СтрЗаменить(лGUID_Строка, "}", "");
// Формируем итоговое имя таблицы
лИмяВТ = "vt_" + лGUID_Строка;
// В результате получим что-то вроде: "vt_bb1a46b765e748248c74640b2741d4df"
Вариант со стандартной компонентой V7Plus.dll
Часто в системе уже зарегистрирована стандартная компонента V7Plus.dll, которая входит в поставку 1С. Она также позволяет генерировать GUID и является предпочтительным вариантом, так как не требует установки сторонних ВК.
// Проверяем, что компонента V7Plus.dll загружена
Попытка
Сервис = СоздатьОбъект("Сервис");
Исключение
Сообщить("Компонента V7Plus.dll не найдена!");
Возврат;
КонецПопытки;
// Генерируем GUID. Параметр 1 означает "без фигурных скобок"
лGUID_Строка = Сервис.ПолучитьGUID(1);
// Строка все еще содержит дефисы, удаляем их
лGUID_Строка_БезДефисов = СтрЗаменить(лGUID_Строка, "-", "");
// Формируем итоговое имя таблицы
лИмяВТ = "vt_" + лGUID_Строка_БезДефисов;
Этот метод практически гарантирует глобальную уникальность имени.
Другой эффективный и очень быстрый способ — использовать значение системного счетчика высокого разрешения с помощью функции _GetPerformanceCounter(). Эта функция возвращает число, которое меняется очень быстро, что делает его отличным кандидатом для создания уникального суффикса.
Преимущество: не требует подключения внешних компонент.
// Получаем текущее значение счетчика
Счетчик = _GetPerformanceCounter();
// Формируем имя таблицы
лИмяВТ = "vt_" + Счетчик;
// Пример результата: "vt_148923456789"
Вероятность коллизии здесь также крайне мала, особенно если префикс vt_ уже подразумевает временный характер таблицы.
Самый простой, но и самый ненадежный способ — использовать отформатированную строку текущей даты и времени.
// Форматируем текущее время в строку без разделителей
ВремяСтрока = Формат(ТекущееВремя(), "ДФ=ггггММддЧЧммсс");
// Формируем имя таблицы
лИмяВТ = "vt_" + ВремяСтрока;
// Пример результата: "vt_20231027154530"
Внимание: Этот метод не рекомендуется для систем с высокой нагрузкой. Если два пользователя выполнят операцию в одну и ту же секунду, имена таблиц совпадут, что приведет к ошибке. Уникальность можно повысить, добавив миллисекунды (если есть функция для их получения) или скомбинировав этот метод со случайным числом, но это усложняет код и не дает таких гарантий, как GUID или счетчик производительности.
Хотя все перечисленные выше способы генерации имен работают, существует более правильный и элегантный подход, предоставляемый самим SQLite. Вместо того чтобы создавать уникально именованную таблицу в основной базе данных, следует использовать специальный синтаксис для создания настоящих временных таблиц.
Для этого в SQL-запросе используются ключевые слова TEMP или TEMPORARY.
CREATE TEMP TABLE МояВременнаяТаблица (
Код INT,
Наименование TEXT,
Сумма REAL
);
Рассмотрим ключевые преимущества такого подхода:
TEMP, видна только в рамках того соединения с базой данных, в котором она была создана. Это означает, что два разных пользователя могут одновременно создать таблицы с абсолютно одинаковым именем (например, "vt_data"), и они не будут мешать друг другу. Проблема коллизии имен исчезает полностью!DROP TABLE и очистке "мусора" в случае аварийного завершения программы.Таким образом, вместо усложнения кода 1С логикой генерации уникальных имен, достаточно просто модифицировать SQL-запрос.
Итог:
Хотя генерация уникальных имен на основе GUID или _GetPerformanceCounter является надежным решением, лучшей практикой при работе с SQLite является использование встроенного механизма CREATE TEMP TABLE. Этот подход проще в реализации, безопаснее и полностью соответствует штатным возможностям СУБД, избавляя вас от лишней работы и потенциальных ошибок в многопользовательской среде.