Как правильно указать значение перечисления в прямом SQL-запросе к базе данных 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с базой данных 1С напрямую через SQL-запросы — это задача, требующая предельной осторожности и глубокого понимания внутренней структуры хранения данных. Одной из типичных трудностей, с которыми сталкиваются разработчики, является вставка или обновление полей, содержащих значения перечислений. В этой статье мы подробно разберем, как формат хранения данных в 1С соотносится с типами данных MS SQL Server, и как правильно составить INSERT запрос, чтобы избежать ошибок приведения типов.

Проблема: Неявное преобразование типов

При попытке выполнить прямой запрос INSERT или UPDATE к таблице 1С (например, к регистру сведений), разработчики часто пытаются передать идентификатор значения перечисления в виде строки. Рассмотрим типичную ситуацию: у нас есть поле _Fld14559RRef, которое в SQL имеет тип binary(16). Если мы попытаемся передать в него значение как строку '0xbc6649eb0a03abb74f3bcabc7117e72a', SQL Server выдаст ошибку:

"Неявное преобразование из типа данных varchar в binary не разрешено. Для выполнения этого запроса используйте функцию CONVERT."

Это происходит потому, что SQL воспринимает данные в кавычках как текстовую строку, а не как последовательность байтов. Проанализируем, как решить эту задачу правильно.

Способ 1. Использование литерала 0x без кавычек

Самое простое и эффективное решение — передать HEX-последовательность напрямую, используя префикс 0x. В языке T-SQL префикс 0x сообщает серверу, что следующие за ним символы являются шестнадцатеричным представлением двоичных данных.

Разберем пример правильного запроса:


INSERT INTO _InfoRg14479([_Fld14483], [_Fld14481], [_Fld14480], [_Fld14482], [_Fld14559RRef])
VALUES ('2021-05-07 17:01:21', '2', '233608', 'ААА', 0xBC6649EB0A03ABB74F3BCABC7117E72A)

Обратите внимание: значение 0xBC6649EB... указано без кавычек. Именно это позволяет SQL Server корректно интерпретировать данные как binary(16) без дополнительных функций преобразования.

Способ 2. Как получить нужное значение перечисления

Чтобы узнать, какой именно набор байтов соответствует конкретному значению перечисления в вашей базе, можно воспользоваться несколькими приемами.

1. Использование SQL Profiler

Мы можем запустить трассировку запросов в SQL Profiler и выполнить простой запрос на встроенном языке 1С:


Запрос = Новый Запрос("ВЫБРАТЬ ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказов.Новый)");
Запрос.Выполнить();

В профайлере мы увидим системный вызов sp_executesql, в котором платформа передает значение в формате 0x.... Это самый надежный способ увидеть "глазами SQL", как выглядит значение метаданных.

2. Программное получение HEX-строки в 1С

Если нам нужно сформировать текст SQL-запроса динамически внутри кода 1С, мы можем воспользоваться методом ЗначениеВСтрокуВнутр(). Рассмотрим функцию, которая преобразует ссылку в формат, пригодный для SQL:


Функция ПолучитьХексДляСкуля(Ссылка) Экспорт
    Если Ссылка.Пустая() Тогда
        Возврат "0x00000000000000000000000000000000";
    КонецЕсли;
    
    // Получаем внутреннее строковое представление
    ВнутрСтр = ЗначениеВСтрокуВнутр(Ссылка); 
    
    // Извлекаем GUID и формируем HEX-литерал
    // Обычно GUID находится в конце внутренней строки
    Результат = "0x" + Лев(Прав(ВнутрСтр, 33), 32);
    Возврат Результат;
КонецФункции

Важно помнить, что 1С хранит GUID в формате со смещенными группами байтов (Byte Swapping). Если вы берете "чистый" GUID из внешних систем, его порядок байтов может отличаться от того, что ожидает 1С в поле _IDRRef.

Особенности структуры таблиц перечислений

Для более глубокого понимания ситуации выясним, как устроены таблицы перечислений в SQL. Каждое перечисление имеет свою таблицу вида _Enum<N>. В ней всегда присутствуют два ключевых поля:

Если вы не знаете точный _IDRRef, вы можете найти его запросом к таблице перечисления, зная порядок (индекс) значения:


SELECT _IDRRef FROM _Enum123 WHERE _EnumOrder = 0 -- получим первое значение перечисления

Важные предостережения при работе через SQL

Проанализируем критические риски, которые возникают при прямой вставке данных в обход объектной модели 1С:

  1. Кэширование объектов: Сервер приложений 1С активно кэширует данные. Если вы измените значение в SQL, сервер 1С может продолжать отдавать пользователям старое значение из своего кэша. Для обновления данных может потребоваться перезапуск службы или очистка серверного кэша.
  2. Целостность данных: При использовании INSERT напрямую в таблицы регистров через SQL, вы берете на себя ответственность за корректность всех связанных полей. 1С не сможет выполнить свои стандартные проверки (например, при подписках на события или в модулях набора записей).
  3. Лицензионное соглашение: Прямая запись в таблицы базы данных 1С сторонними средствами официально запрещена лицензионным соглашением (за исключением некоторых случаев).

Резюме

Для того чтобы успешно указать значение перечисления в SQL-запросе, придерживайтесь следующего алгоритма:

  1. Определите _IDRRef нужного значения (через профайлер или таблицу _Enum).
  2. В тексте SQL-запроса указывайте значение с префиксом 0x.
  3. Не используйте кавычки вокруг шестнадцатеричного числа.
  4. Для надежности в сложных выражениях можно использовать явное приведение: CAST(0xBC66... AS binary(16)).

Следуя этим правилам, вы обеспечите техническую корректность выполнения ваших запросов к СУБД.

← На главную