При переходе на использование прямых SQL-запросов к таблицам DBF через внешнюю компоненту 1SQLite разработчики 1С:Предприятия 7.7 часто сталкиваются с проблемой фильтрации пустых ссылок. Попытка написать простое условие вида WHERE Реквизит <> '' или WHERE Реквизит <> ' ' не дает желаемого результата — запрос либо возвращает пустые строки, либо отфильтровывает лишние данные.
Разберем внутреннее устройство хранения ссылок в DBF-файлах платформы 1С 7.7 и рассмотрим правильные варианты построения условий в запросах 1SQLite.
Проанализируем структуру хранения ссылочных типов в формате базы данных 1С 7.7:
Справочник.Номенклатура), его идентификатор хранится в виде строки фиксированной длины (9 символов в системе счисления Base36). Физически пустое значение ссылки представлено не просто девятью пробелами, а специальной комбинацией: ' 0 ' (три пробела, ноль и пять пробелов).' 0 0 '.Именно поэтому стандартное сравнение со строкой из произвольного числа пробелов не совпадает с внутренним представлением пустой ссылки.
В компоненте 1SQLite реализован набор предопределенных текстовых макросов, которые движок автоматически заменяет на корректные бинарные и строковые представления системных значений 1С 7.7. Для фильтрации пустых ссылок типизированных полей достаточно использовать макрос :ПустойИД.
Посмотрим на пример запроса к табличной части документа:
ТекстЗапроса = "
|SELECT
| ЗаявкаНаТоварыСтроки.тчТМЦ as [Товар $Справочник.Номенклатура],
| ЗаявкаНаТоварыСтроки.Количество as Количество
|FROM
| [ДокументСтроки.ЗаявкаНаТовары] AS ЗаявкаНаТоварыСтроки
|WHERE
| ЗаявкаНаТоварыСтроки.тчТМЦ <> :ПустойИД
|";
Преимущества этого подхода:
Другой надежный способ — передача типизированного пустого значения через механизм параметров запроса. Для этого используется метод Подставлять (или УстановитьПараметр) объекта SQLiteQuery в сочетании с платформенной функцией ПолучитьПустоеЗначение().
Рассмотрим реализацию в программном коде:
Запрос = СоздатьОбъект("SQLiteQuery");
ТекстЗапроса = "
|SELECT
| ЗаявкаНаТоварыСтроки.тчТМЦ as [Товар $Справочник.Номенклатура],
| ЗаявкаНаТоварыСтроки.Количество as Количество
|FROM
| [ДокументСтроки.ЗаявкаНаТовары] AS ЗаявкаНаТоварыСтроки
|WHERE
| ЗаявкаНаТоварыСтроки.тчТМЦ <> :ПустаяСсылка
|";
Запрос.Подставлять("ПустаяСсылка", ПолучитьПустоеЗначение("Справочник.Номенклатура"));
ТЗ = Запрос.ВыполнитьЗапрос(ТекстЗапроса);
При таком вызове компонента 1SQLite автоматически распознает тип переданного объекта 1С и выполняет преобразование в требуемый формат для сравнения внутри базы данных.
Если поле в базе данных имеет составной тип или проверяется пустота даты, следует использовать соответствующие макросы 1SQLite:
:ПустойИД13 (или :EmptyID13) — применяется для реквизитов неопределенного (составного) типа данных.:ПустаяДата (или :EmptyDate) — подставляет строковое представление пустой даты базы данных.Пример использования для поля составного типа:
ТекстЗапроса = "
|SELECT
| Док.Субконто as Субконто
|FROM
| [Документ.Операция] AS Док
|WHERE
| Док.Субконто <> :ПустойИД13
|";
Иногда для отсечения пустых значений используют строковые функции, например WHERE TRIM(ЗаявкаНаТоварыСтроки.тчТМЦ) <> ''. Следует учитывать, что применение любых функций к колонкам в блоке WHERE отключает использование индексов по этому полю. В результате SQLite переходит к полному сканированию таблицы (Full Table Scan), что существенно замедляет выполнение запроса на больших базах данных.
Для сохранения максимального быстродействия рекомендуется всегда использовать макрос :ПустойИД или прямую передачу параметров через Подставлять.