При работе со строковыми полями неограниченной длины (например, реквизиты Комментарий или Содержание) разработчики часто сталкиваются с ситуацией, когда пользователь случайно или намеренно нажимает клавишу Enter и сохраняет документ. В базе данных появляется строка, которая визуально кажется пустой, но физически содержит непечатаемые символы переноса строки (Символы.ПС или Символы.ВК).
Стандартное условие проверки равенства пустой строке в языке запросов вида ВЫРАЗИТЬ(Таблица.Комментарий КАК СТРОКА(100)) = "" в таком случае возвращает ЛОЖЬ, так как СУБД отсекает только конечные пробелы, но не непечатаемые символы переноса. В языке запросов 1С отсутствуют прямые аналоги функций ЗначениеЗаполнено() или СокрЛП(). Проанализируем возможные решения этой задачи.
Выясним причину, почему обычное сравнение не приносит результата:
Строка неограниченной длины нельзя использовать в операциях сравнения запроса напрямую без использования конструкции ВЫРАЗИТЬ().CR / LF) и символ табуляции являются полноценными символами с точки зрения СУБД. Поле, содержащее только перенос строки, физически не является пустым.Наиболее эффективный подход с точки зрения производительности базы данных — не допускать попадания «псевдопустых» строк в базу данных. Для этого выполним очистку реквизита в обработчике события ПередЗаписью объекта (документа или справочника).
Рассмотрим пример кода в модуле объекта:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Удаляем концевые и начальные пробелы, а также проверяем на заполненность
Если НЕ ЗначениеЗаполнено(СокрЛП(Комментарий)) Тогда
Комментарий = "";
КонецЕсли;
КонецПроцедуры
При таком подходе строка, содержащая только пробелы, переносы или табуляции, очищается до значения "". В результате стандартная проверка в запросе снова начинает работать безотказно:
ВЫБРАТЬ
Реализация.Ссылка КАК Ссылка
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
ВЫРАЗИТЬ(Реализация.Комментарий КАК СТРОКА(100)) = ""
Если изменить логику записи данных невозможно и требуется обработать уже существующие записи непосредственно в запросе, разберем вариант с проверкой первых символов строки.
Передадим в параметр запроса символ переноса строки Символы.ПС и выполним проверку через функцию ПОДСТРОКА():
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Таблица.Ссылка КАК Ссылка,
| ВЫБОР
| КОГДА ПОДСТРОКА(ВЫРАЗИТЬ(Таблица.Комментарий КАК СТРОКА(100)), 1, 1) = """" Тhen ИСТИНА
| КОГДА ПОДСТРОКА(ВЫРАЗИТЬ(Таблица.Комментарий КАК СТРОКА(100)), 1, 1) = &ПС Тhen ИСТИНА
| ИНАЧЕ ЛОЖЬ
| КОНЕЦ КАК ЭтоПустаяСтрока
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Таблица";
Запрос.УстановитьПараметр("ПС", Символы.ПС);
Для более комплексной проверки на наличие хотя бы одного значащего символа (буквы, цифры или знака) во всей строке можно применить оператор ПОДОБНО с исключением непечатаемых символов и пробелов.
Сформируем шаблон поиска и передадим его в параметр:
ШаблонПоиска = "%[^" + Символы.ПС + Символы.ВК + Символы.Таб + " ]%";
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Таблица.Ссылка КАК Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Таблица
|ГДЕ
| НЕ ВЫРАЗИТЬ(Таблица.Комментарий КАК СТРОКА(1000)) ПОДОБНО &Шаблон";
Запрос.УстановитьПараметр("Шаблон", ШаблонПоиска);
Обратите внимание: Использование сложных шаблонов с отрицанием в ПОДОБНО может не поддерживаться в некоторых СУБД (например, IBM DB2) и снижает скорость выполнения запроса из-за невозможности использования индексов.
Если запрос разрабатывается для отчета на СКД, оптимальным решением будет перенос логики проверки в Вычисляемые поля компоновки данных. Язык выражений СКД поддерживает встроенную функцию ПустаяСтрока(), которая корректно обрабатывает переносы строк и пробелы.
Посмотрим на пример выражения в вычисляемом поле СКД:
ПустаяСтрока(Комментарий)
Выражение вернет значение ИСТИНА, если поле содержит только непечатаемые символы, что позволит легко отфильтровать нужные строки в настройках отчета.