Как в прямом запросе SQLite для 1С 7.7 проверить реквизит на пустое значение

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

При переходе на использование прямых SQL-запросов к таблицам DBF через внешнюю компоненту 1SQLite разработчики 1С:Предприятия 7.7 часто сталкиваются с проблемой фильтрации пустых ссылок. Попытка написать простое условие вида WHERE Реквизит <> '' или WHERE Реквизит <> ' ' не дает желаемого результата — запрос либо возвращает пустые строки, либо отфильтровывает лишние данные.

Разберем внутреннее устройство хранения ссылок в DBF-файлах платформы 1С 7.7 и рассмотрим правильные варианты построения условий в запросах 1SQLite.

Почему простое сравнение с пробелами не работает

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

  1. Типизированные реквизиты: если у реквизита строго указан тип (например, Справочник.Номенклатура), его идентификатор хранится в виде строки фиксированной длины (9 символов в системе счисления Base36). Физически пустое значение ссылки представлено не просто девятью пробелами, а специальной комбинацией: ' 0 ' (три пробела, ноль и пять пробелов).
  2. Реквизиты неопределенного типа: если реквизит может принимать значения разных типов, длина поля составляет 13 символов (префиксы типа, вида и сам 9-символьный идентификатор). Пустое значение в таком поле хранится как ' 0 0 '.

Именно поэтому стандартное сравнение со строкой из произвольного числа пробелов не совпадает с внутренним представлением пустой ссылки.

Способ 1. Использование предопределенного параметра :ПустойИД (рекомендуемый)

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

Посмотрим на пример запроса к табличной части документа:


ТекстЗапроса = "
|SELECT
|    ЗаявкаНаТоварыСтроки.тчТМЦ as [Товар $Справочник.Номенклатура],
|    ЗаявкаНаТоварыСтроки.Количество as Количество
|FROM
|    [ДокументСтроки.ЗаявкаНаТовары] AS ЗаявкаНаТоварыСтроки
|WHERE
|    ЗаявкаНаТоварыСтроки.тчТМЦ <> :ПустойИД
|";

Преимущества этого подхода:

  1. Читаемость: код запроса остается компактным и понятным.
  2. Оптимизация: макрос разворачивается в точное строковое значение, что позволяет движку SQLite полноценно задействовать существующие индексы таблицы DBF без просадки производительности.

Способ 2. Подстановка типизированного пустого значения из 1С

Другой надежный способ — передача типизированного пустого значения через механизм параметров запроса. Для этого используется метод Подставлять (или УстановитьПараметр) объекта SQLiteQuery в сочетании с платформенной функцией ПолучитьПустоеЗначение().

Рассмотрим реализацию в программном коде:


Запрос = СоздатьОбъект("SQLiteQuery");
ТекстЗапроса = "
|SELECT
|    ЗаявкаНаТоварыСтроки.тчТМЦ as [Товар $Справочник.Номенклатура],
|    ЗаявкаНаТоварыСтроки.Количество as Количество
|FROM
|    [ДокументСтроки.ЗаявкаНаТовары] AS ЗаявкаНаТоварыСтроки
|WHERE
|    ЗаявкаНаТоварыСтроки.тчТМЦ <> :ПустаяСсылка
|";

Запрос.Подставлять("ПустаяСсылка", ПолучитьПустоеЗначение("Справочник.Номенклатура"));
ТЗ = Запрос.ВыполнитьЗапрос(ТекстЗапроса);

При таком вызове компонента 1SQLite автоматически распознает тип переданного объекта 1С и выполняет преобразование в требуемый формат для сравнения внутри базы данных.

Работа с неопределенными типами и датами

Если поле в базе данных имеет составной тип или проверяется пустота даты, следует использовать соответствующие макросы 1SQLite:

  1. :ПустойИД13 (или :EmptyID13) — применяется для реквизитов неопределенного (составного) типа данных.
  2. :ПустаяДата (или :EmptyDate) — подставляет строковое представление пустой даты базы данных.

Пример использования для поля составного типа:


ТекстЗапроса = "
|SELECT
|    Док.Субконто as Субконто
|FROM
|    [Документ.Операция] AS Док
|WHERE
|    Док.Субконто <> :ПустойИД13
|";

Почему не стоит использовать TRIM() для проверки ссылок

Иногда для отсечения пустых значений используют строковые функции, например WHERE TRIM(ЗаявкаНаТоварыСтроки.тчТМЦ) <> ''. Следует учитывать, что применение любых функций к колонкам в блоке WHERE отключает использование индексов по этому полю. В результате SQLite переходит к полному сканированию таблицы (Full Table Scan), что существенно замедляет выполнение запроса на больших базах данных.

Для сохранения максимального быстродействия рекомендуется всегда использовать макрос :ПустойИД или прямую передачу параметров через Подставлять.

← На главную