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

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

Работа с прямыми SQL-запросами в среде 1С:Предприятие 7.7 с использованием расширения 1С++ открывает огромные возможности для оптимизации производительности. Однако начинающие разработчики часто сталкиваются с проблемой «магических чисел» и непониманием того, как платформа хранит ссылки на объекты в таблицах базы данных. Одной из таких задач является получение внутреннего идентификатора вида документа и корректная передача ссылки в запрос.

В этой статье мы подробно разберем, как устроено внутреннее представление документа в SQL, зачем нужны модификаторы параметров в 1С++ и как правильно искать документы по реквизитам неопределенного типа, таким как ДокументОснование.

Внутренняя структура ссылки на документ в 1С 7.7

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

  1. Типизированный реквизит (например, тип «Документ.ТТН»): в базе SQL создается поле длиной 9 символов. В нем хранится только уникальный идентификатор конкретного документа — IDDoc.
  2. Нетипизированный реквизит (тип «Документ» или «ОбщийРеквизит» с неопределенным типом): в SQL создается поле длиной 13 символов. Это составное поле, которое включает в себя:
    • Первые 4 символа — IDDocDef (идентификатор вида документа).
    • Следующие 9 символов — IDDoc (идентификатор самого экземпляра).

Именно эти 13-символьные строки часто выглядят в консоли запросов как странные конструкции вида ' 52X 171 '. Здесь первые четыре знака (с учетом пробелов) определяют, что это за документ (например, «Закупка»), а остальные девять — какой именно это документ в списке «Закупок».

Система счисления Base36 и класс MetaDataWork

Выясним причину, по которой обычные числовые идентификаторы из метаданных не совпадают с тем, что мы видим в SQL. В 1С 7.7 используется тридцатьшестеричная система счисления (Base36), включающая цифры 0-9 и латинские буквы A-Z.

Рассмотрим ситуацию: метод MetaDataWork.ИДДокумента("Закупка") возвращает число 1549. Однако в SQL-таблице вы увидите не 1549, а его представление в Base36, дополненное пробелами слева до 4 символов. Попытка вручную «склеить» строку для запроса часто приводит к ошибкам, так как лишний или недостающий пробел сделает условие WHERE ложным.

Использование модификаторов параметров 1С++

Для решения проблем с преобразованием типов в 1С++ предусмотрен механизм модификаторов. Это специальный «синтаксический сахар», который автоматически подготавливает значение переменной 1С для SQL-сервера. Рассмотрим основные модификаторы для документов:

  1. :Параметр — базовый вариант. Если 1С++ может однозначно определить тип из контекста запроса, он подставит нужное значение.
  2. :Параметр~ (тильда) — самый важный модификатор для работы с неопределенными типами. Он заставляет 1С++ представить объект в виде полной 13-символьной строки (IDDocDef + IDDoc). Это именно то, что нужно для поиска по общему реквизиту ДокументОснование.
  3. :Параметр* (звездочка) — передает только 9-символьный IDDoc. Используется, когда вы делаете выборку из таблицы конкретного вида документа, где вид уже известен системе.

Практический пример: поиск документа по основанию

Разберем ситуацию, описанную в теме форума. Нам нужно найти документ «ТТН_ЕГАИС_Входящая», у которого в реквизите ДокументОснование указан конкретный документ (например, «ПоступлениеТоваров»). Поскольку ДокументОснование — это реквизит неопределенного типа, в базе он хранится как 13 символов.

Проанализируем правильный код запроса:


ТекстЗапроса = "
|SELECT
|    ТТН.IDDoc as [ТТН $Документ.ТТН_ЕГАИС_Входящая]
|FROM
|    $Документ.ТТН_ЕГАИС_Входящая as ТТН
|WHERE
|    ТТН.$ОбщийРеквизит.ДокументОснование = :Парам~";

Запрос = СоздатьОбъект("ODBCRecordset");
Запрос.УстановитьТекстовыйПараметр("Парам", ДокументСсылка);
Результат = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);

В данном примере использование модификатора ~ гарантирует, что 1С++ возьмет ссылку ДокументСсылка, определит ее вид, переведет его в Base36, дополнит пробелами до 4 символов, приклеит к нему 9 символов ID документа и передаст в SQL строку ровно из 13 символов. Это избавляет разработчика от необходимости вручную вычислять идентификаторы через MetaDataWork.

Дополнительные возможности MetaDataWork (MDW)

Хотя модификаторы решают большинство задач, иногда требуется получить идентификатор типа вручную (например, для динамического построения текста запроса). В классе MetaDataWork для этого существуют специальные методы:

Разберем пример ручного получения идентификатора, если по какой-то причине модификатор не подходит:


MDW = СоздатьОбъект("MetaDataWork");
ИДТипа = MDW.ИДДокументаSQL("Закупка"); // Вернет что-то вроде " 52X"
Сообщить("Внутренний префикс типа: '" + ИДТипа + "'");

Подведем итоги

При работе с прямыми запросами в 1С 7.7 важно помнить о разнице между 9-символьными и 13-символьными идентификаторами. Попытка сравнить их напрямую в SQL без учета префикса типа (IDDocDef) — классическая ошибка, приводящая к пустым результатам запроса.

Основные правила для запоминания:

  1. Всегда используйте модификатор ~ при сравнении с реквизитами типа «Документ» (неопределенный).
  2. Помните, что пробелы в начале идентификатора типа — это не ошибка отображения, а часть структуры данных, необходимая для выравнивания строки до 4 символов.
  3. Используйте конструкцию $ВидДокумента.НазваниеВида прямо в тексте запроса, если вам нужно жестко ограничить выборку по конкретному типу в сложном условии.

Использование механизмов 1С++ позволяет писать чистый и надежный код, абстрагируясь от сложностей внутреннего хранения данных в 1С 7.7, обеспечивая при этом максимальную скорость работы с базой данных SQL.

← На главную