При работе с крупными конфигурациями, такими как УПП (Управление производственным предприятием) или ERP, разработчики часто сталкиваются с аппаратным ограничением SQL-сервера. Ошибка с текстом Microsoft SQL Native Client: Too many table names in the query. The maximum allowable is 256 означает, что итоговый запрос, сформированный платформой 1С, пытается одновременно обратиться к более чем 256 таблицам базы данных. Разберем, почему это происходит и как правильно перестроить запрос, чтобы он работал быстро и стабильно.
Основная причина кроется в механизме работы 1С с составными типами данных. В языке запросов 1С мы часто обращаемся к реквизитам объектов через точку. Например, обращение ДокументОснование.Комментарий выглядит просто и лаконично. Однако на уровне СУБД (SQL Server) это превращается в сложную конструкцию соединений.
Проанализируем ситуацию: если поле ДокументОснование в метаданных может принимать значения 150 различных типов документов, то при обращении к любому его реквизиту (например, .Комментарий) платформа 1С вынуждена выполнить LEFT JOIN (левое соединение) со всеми 150 таблицами этих документов. Если в запросе задействовано несколько таких полей или используются сложные виртуальные таблицы (например, ОборотыБюджетов, у которой огромное количество регистраторов), лимит в 256 таблиц исчерпывается мгновенно.
Важно понимать, что использование ВЫРАЗИТЬ(ДокументОснование.Комментарий КАК СТРОКА(100)) само по себе не уменьшает количество таблиц в SQL-запросе. Эта функция лишь ограничивает длину результирующей строки, но не отменяет необходимость соединения со всеми возможными таблицами документов для поиска этого самого комментария.
Самый эффективный способ оптимизировать такой запрос — это подсказать платформе, из каких именно типов документов мы хотим получить данные. Рассмотрим, как переписать обращение к комментарию, чтобы отсечь лишние соединения. Вместо прямого обращения через точку используем конструкцию ВЫРАЗИТЬ для конкретных типов документов.
Посмотрим на пример правильного написания кода:
ВЫБОР
КОГДА ОборотыБюджетов.ДокументОснование ССЫЛКА Документ.ПлатежноеПоручениеИсходящее
ТОГДА ВЫРАЗИТЬ(ВЫРАЗИТЬ(ОборотыБюджетов.ДокументОснование КАК Документ.ПлатежноеПоручениеИсходящее).Комментарий КАК СТРОКА(100))
КОГДА ОборотыБюджетов.ДокументОснование ССЫЛКА Документ.ПлатежноеПоручениеВходящее
ТОГДА ВЫРАЗИТЬ(ВЫРАЗИТЬ(ОборотыБюджетов.ДокументОснование КАК Документ.ПлатежноеПоручениеВходящее).Комментарий КАК СТРОКА(100))
ИНАЧЕ NULL
КОНЕЦ КАК Комментарий
Что здесь изменилось? Когда мы пишем ВЫРАЗИТЬ(Поле КАК Документ.ИмяТипа), платформа понимает, что соединение нужно строить только с одной конкретной таблицей этого документа. В данном случае SQL-запрос будет содержать соединения только с таблицами ПлатежноеПоручениеИсходящее и ПлатежноеПоручениеВходящее, вместо сотни других типов, которые могут храниться в ДокументОснование.
Если нам нужно получить данные из регистра и соединить их с реквизитами документов, самым профессиональным подходом будет разделение запроса на части с использованием временных таблиц. Разберем этот алгоритм по шагам:
ОборотыБюджетов и помещаем их во временную таблицу ВТ_ДанныеРегистра. На этом этапе мы не обращаемся к реквизитам документов через точку.ДокументОснование во временной таблице для ускорения последующих соединений.ВТ_ДанныеРегистра и делаем явное ЛЕВОЕ СОЕДИНЕНИЕ только с теми таблицами документов, которые нам действительно нужны (например, только банковские документы).Рассмотрим пример реализации такого пакета запросов:
// Запрос 1: Собираем данные во временную таблицу
ВЫБРАТЬ
ОборотыБюджетов.Период,
ОборотыБюджетов.Регистратор,
ОборотыБюджетов.ДокументОснование,
ОборотыБюджетов.СуммаУпр КАК Сумма
ПОМЕСТИТЬ ВТ_Данные
ИЗ
РегистрНакопления.ОборотыБюджетов КАК ОборотыБюджетов
ГДЕ
ОборотыБюджетов.Период МЕЖДУ &НачалоПериода И &КонецПериода
ИНДЕКСИРОВАТЬ ПО
ДокументОснование
;
// Запрос 2: Соединяем только с нужными таблицами
ВЫБРАТЬ
ВТ_Данные.Период,
ВТ_Данные.Сумма,
ЕСТЬNULL(ППИ.Комментарий, ЕСТЬNULL(ППВ.Комментарий, "")) КАК Комментарий
ИЗ
ВТ_Данные КАК ВТ_Данные
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПлатежноеПоручениеИсходящее КАК ППИ
ПО ВТ_Данные.ДокументОснование = ППИ.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПлатежноеПоручениеВходящее КАК ППВ
ПО ВТ_Данные.ДокументОснование = ППВ.Ссылка
Этот метод гарантирует, что количество таблиц в каждом отдельном SQL-запросе пакета будет минимальным. Даже если в регистре 200 типов регистраторов, во втором запросе SQL-сервер увидит всего 3 таблицы: саму временную таблицу и две таблицы платежных поручений.
Проанализируем ситуацию, когда нам вообще не нужны данные по другим типам документов. Если отчет строится только по конкретным видам документов, мы можем жестко ограничить выборку в условии ГДЕ. Это позволит оптимизатору запросов 1С исключить лишние таблицы из плана выполнения.
Например, добавим фильтр по типам:
ГДЕ
(ОборотыБюджетов.ДокументОснование ССЫЛКА Документ.ПлатежноеПоручениеИсходящее
ИЛИ ОборотыБюджетов.ДокументОснование ССЫЛКА Документ.ПлатежноеПоручениеВходящее)
Однако помните, что этот способ подходит только в том случае, если логика отчета позволяет отсечь все остальные документы. В ситуации автора темы (когда нужны обороты по всем, а комментарии только по некоторым) этот способ следует комбинировать с первым или вторым вариантом.
Регистр ОборотыБюджетов в конфигурации УПП является классическим примером "перегруженного" объекта. У него может быть более сотни типов регистраторов. Проанализируем дополнительные рекомендации для таких случаев:
СГРУППИРОВАТЬ ПО. Группировка по полю ДокументОснование.Комментарий заставляет SQL Server выполнять титаническую работу по соединению и сортировке огромного количества таблиц.ДокументОснование, а из-за вывода поля Регистратор в список полей запроса без последующей агрегации. Если вам не нужен номер или дата регистратора, старайтесь не обращаться к его реквизитам напрямую.Подведем итог: ошибка "слишком много таблиц" — это сигнал о том, что запрос перестал быть "прозрачным" для СУБД. Использование ВЫРАЗИТЬ для типизации составных полей и переход на временные таблицы — это стандарт индустрии 1С, который позволяет не только обойти ограничение в 256 таблиц, но и значительно ускорить формирование отчетов.