Как создать уникальное имя для временной таблицы в 1SQLite из 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При работе с внешними базами данных, такими как SQLite, из 1С 7.7 часто возникает задача создания временных таблиц для промежуточных расчетов. В многопользовательской среде это порождает проблему: как назвать таблицу так, чтобы избежать конфликтов, когда несколько пользователей одновременно выполняют одну и ту же операцию? Простое, статичное имя вроде "vt_temp_data" неминуемо приведет к ошибкам.

Рассмотрим несколько подходов к генерации уникального имени для временной таблицы, а также разберем лучший, нативный способ работы с временными данными в SQLite, который полностью избавляет от этой проблемы.

Зачем нужно уникальное имя и какие есть ограничения?

Основная причина — избежание коллизий. Если два процесса попытаются одновременно создать или записать данные в таблицу с одинаковым именем в общей базе данных, возникнет ошибка или данные одного процесса перезапишут данные другого. Кроме того, при генерации имени важно учитывать технические ограничения самой СУБД SQLite.

  1. Допустимые символы. Имена таблиц в SQLite могут содержать буквы, цифры и знак подчеркивания _. Использование других символов, например дефиса -, недопустимо и вызовет ошибку SQL. Если все же необходимо использовать спецсимволы, имя нужно заключать в двойные кавычки, но лучше этого избегать.
  2. Длина имени. Хотя теоретический предел длины имени в SQLite очень большой, на практике рекомендуется придерживаться длины до 64 символов для совместимости с различными инструментами и драйверами.

Теперь проанализируем, как можно сгенерировать подходящее имя средствами 1С 7.7.

Способ 1: Использование GUID (глобально уникального идентификатора)

Это самый надежный способ обеспечить уникальность. 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_Строка_БезДефисов;

Этот метод практически гарантирует глобальную уникальность имени.

Способ 2: Использование системного счетчика производительности

Другой эффективный и очень быстрый способ — использовать значение системного счетчика высокого разрешения с помощью функции _GetPerformanceCounter(). Эта функция возвращает число, которое меняется очень быстро, что делает его отличным кандидатом для создания уникального суффикса.

Преимущество: не требует подключения внешних компонент.


// Получаем текущее значение счетчика
Счетчик = _GetPerformanceCounter();

// Формируем имя таблицы
лИмяВТ = "vt_" + Счетчик;

// Пример результата: "vt_148923456789"

Вероятность коллизии здесь также крайне мала, особенно если префикс vt_ уже подразумевает временный характер таблицы.

Способ 3: Использование текущего времени

Самый простой, но и самый ненадежный способ — использовать отформатированную строку текущей даты и времени.


// Форматируем текущее время в строку без разделителей
ВремяСтрока = Формат(ТекущееВремя(), "ДФ=ггггММддЧЧммсс");

// Формируем имя таблицы
лИмяВТ = "vt_" + ВремяСтрока;

// Пример результата: "vt_20231027154530"

Внимание: Этот метод не рекомендуется для систем с высокой нагрузкой. Если два пользователя выполнят операцию в одну и ту же секунду, имена таблиц совпадут, что приведет к ошибке. Уникальность можно повысить, добавив миллисекунды (если есть функция для их получения) или скомбинировав этот метод со случайным числом, но это усложняет код и не дает таких гарантий, как GUID или счетчик производительности.

Рекомендованный подход: встроенные временные таблицы SQLite

Хотя все перечисленные выше способы генерации имен работают, существует более правильный и элегантный подход, предоставляемый самим SQLite. Вместо того чтобы создавать уникально именованную таблицу в основной базе данных, следует использовать специальный синтаксис для создания настоящих временных таблиц.

Для этого в SQL-запросе используются ключевые слова TEMP или TEMPORARY.


CREATE TEMP TABLE МояВременнаяТаблица (
    Код INT,
    Наименование TEXT,
    Сумма REAL
);

Рассмотрим ключевые преимущества такого подхода:

  1. Полная изоляция. Временная таблица, созданная с ключевым словом TEMP, видна только в рамках того соединения с базой данных, в котором она была создана. Это означает, что два разных пользователя могут одновременно создать таблицы с абсолютно одинаковым именем (например, "vt_data"), и они не будут мешать друг другу. Проблема коллизии имен исчезает полностью!
  2. Автоматическая очистка. Временная таблица автоматически удаляется, как только соединение с базой данных закрывается. Вам больше не нужно беспокоиться о написании кода для DROP TABLE и очистке "мусора" в случае аварийного завершения программы.

Таким образом, вместо усложнения кода 1С логикой генерации уникальных имен, достаточно просто модифицировать SQL-запрос.

Итог:

Хотя генерация уникальных имен на основе GUID или _GetPerformanceCounter является надежным решением, лучшей практикой при работе с SQLite является использование встроенного механизма CREATE TEMP TABLE. Этот подход проще в реализации, безопаснее и полностью соответствует штатным возможностям СУБД, избавляя вас от лишней работы и потенциальных ошибок в многопользовательской среде.

← На главную