Особенность выполнения функции ПОДСТРОКА() языка запросов

Раздел содержит описание особенности выполнения функции ПОДСТРОКА() языка запросов в клиент-серверном варианте работы и вытекающие из нее рекомендации по построению запросов.

Функция ПОДСТРОКА()

В языке запросов 1С:Предприятия функция ПОДСТРОКА() в формате ПОДСТРОКА(<Исходная строка>, <Начало>, <Длина>) может применяться к данным строкового типа и позволяет выделить фрагмент <Исходной строки>, начинающийся с символа номер <Начало> (символы в строке нумеруются с 1) и длиной <Длина> символов. Результат вычисления функции ПОДСТРОКА() имеет строковый тип переменной длины, причем длина будет считаться неограниченной, если <Исходная строка> имеет неограниченную длину и параметр <Длина> не является константой или превышает 1024.

Вычисление функции ПОДСТРОКА() на SQL сервере

В клиент-серверном варианте работы функция ПОДСТРОКА() реализуется при помощи функции SUBSTRING() соответствующего оператора SQL, передаваемого серверу баз данных SQL Server, который вычисляет тип результата функции SUBSTRING() по сложным правилам в зависимости от типа и значений ее параметров, а так же в зависимости от контекста, в котором она используется.

В большинстве случаев эти правила не оказывают влияния на выполнение запроса 1С:Предприятия, однако есть случаи, когда для исполнения запроса существенна максимальная длина строки результата, вычисленная SQL Server. Важно иметь в виду, что в некоторых контекстах использования функции ПОДСТРОКА() максимальная длина ее результата может оказаться равной максимальной длине строки ограниченной длины, которая в SQL Server равна 4000 символам. Это может привести к неожиданному аварийному завершению выполнения запроса.

Например, запрос:

Копировать в буфер обмена

ВЫБРАТЬ
    ВЫБОР
        КОГДА Вид = &ЮрАдресФизЛица 
        ТОГДА ПОДСТРОКА(Представление, 0, 200) 
        ИНАЧЕ NULL 
    КОНЕЦ КАК Представление,
    ВЫБОР
        КОГДА Вид = &ЮрАдресФизЛица 
        ТОГДА ПОДСТРОКА(Представление, 0, 200) 
        ИНАЧЕ NULL 
    КОНЕЦ КАК Представление1
ИЗ
    РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
УПОРЯДОЧИТЬ ПО
    Представление,
    Представление1

завершается аварийно с сообщением:

Ошибка СУБД:
Microsoft OLE DB Provider for SQL Server: Warning: The query processor could not produce a query plan from the optimizer because the total length of all the columns in the GROUP BY or ORDER BY clause exceeds 8000 bytes.
HRESULT=80040E14, SQLSTATE=42000, native=8618

Это происходит потому, что вычисленная Microsoft SQL Server максимальная длина строки, которая является результатом выражения:

Копировать в буфер обмена

ВЫБОР
    КОГДА Вид = &ЮрАдресФизЛица 
    ТОГДА ПОДСТРОКА(Представление, 0, 200) 
    ИНАЧЕ NULL 
КОНЕЦ КАК Представление,

равна 4000 символов. Поэтому длина записи, состоящей из двух таких полей превышает 8000 байт, разрешенные для выполнения операции сортировки.

В связи с описанной особенностью исполнения функции SUBSTRING() на SQL Server использование функции ПОДСТРОКА() с целью приведения строк неограниченной длины к строкам ограниченной длины не рекомендуется. Вместо нее лучше использовать операцию приведения типа ВЫРАЗИТЬ(). В частности, приведенный пример можно переписать в виде:

Копировать в буфер обмена

ВЫБРАТЬ
    ВЫБОР
        КОГДА Вид = &ЮрАдресФизЛица 
        ТОГДА ВЫРАЗИТЬ(Представление КАК Строка(200)) 
        ИНАЧЕ NULL 
    КОНЕЦ КАК Представление,
    ВЫБОР
        КОГДА Вид = &ЮрАдресФизЛица 
        ТОГДА ВЫРАЗИТЬ(Представление КАК Строка(200)) 
        ИНАЧЕ NULL 
    КОНЕЦ КАК Представление1
ИЗ
    РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
УПОРЯДОЧИТЬ ПО 
    Представление,
    Представление1