Что делать, если в 1С:УТ возникает ошибка SQL "Не удалось привязать составной идентификатор" в обработке "Обеспечение потребностей"?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В этой статье разберем ситуацию, когда при работе со стандартной обработкой "Обеспечение потребностей" в "1С:Управление торговлей" система внезапно начинает выдавать невосстановимую ошибку СУБД. Проанализируем причины ее появления и по шагам рассмотрим, как это исправить.

Часто проблема проявляется после обновления конфигурации или незначительных изменений в настройках, сделанных пользователем. Система сообщает об ошибке при выполнении запроса POST, указывая на проблему со стороны MS SQL Server:


Ошибка СУБД:
Microsoft OLE DB Driver for SQL Server: Не удалось привязать составной идентификатор "T3._Fld3555_TYPE".
HRESULT=80040E14, SQLSrvr: SQLSTATE=42S22, native=4104

Эта ошибка означает, что оптимизатор запросов MS SQL Server не смог сопоставить поле из запроса (`T3._Fld3555_TYPE`) ни с одной из таблиц. Давайте выясним, почему платформа 1С генерирует такой "непонятный" для SQL Server запрос и как это исправить.

Анализ проблемы: почему возникает ошибка?

Корень проблемы, как выяснилось в ходе обсуждения, кроется в использовании одного и того же дополнительного реквизита для нескольких типов документов, особенно когда этот реквизит используется в отборах в сложных отчетах или обработках, построенных на Системе Компоновки Данных (СКД). Обработка "Обеспечение потребностей" — яркий тому пример.

Рассмотрим ситуацию: пользователь создал дополнительный реквизит, например, "Своя дата доставки", и назначил его документу "Заказ клиента". Все работало хорошо. Позже, для унификации, этот же допреквизит был добавлен к другому типу документа, например, "Заявка на возврат товаров от клиента". Как только пользователь попытался использовать отбор по этому "общему" реквизиту в обработке, система сломалась.

Происходит следующее:

  1. СКД строит универсальный запрос. Чтобы получить значение общего допреквизита, СКД должна учесть все возможные типы документов-владельцев. Для этого она динамически генерирует очень сложный SQL-запрос.
  2. Генерируются множественные соединения. В итоговом SQL-коде появляются левые соединения (LEFT JOIN) с таблицами дополнительных реквизитов каждого типа документа, которому назначен этот реквизит.
  3. SQL Server "теряется". Из-за сложности сгенерированной конструкции, наличия вложенных подзапросов и множества псевдонимов таблиц (T1, T2, T3 и т.д.), оптимизатор MS SQL Server "теряет контекст" и не может понять, к какой из таблиц относится то или иное поле. Это и приводит к ошибке "Не удалось привязать составной идентификатор".

В ходе отладки был получен упрощенный фрагмент запроса, который вызывал ошибку. Обратите внимание на его структуру:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
	null как поле
ИЗ
	(ВЫБРАТЬ
		0 КАК Поле1) КАК ВложенныйЗапрос
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаявкаНаВозвратТоваровОтКлиента.ДополнительныеРеквизиты КАК ЗаявкаНаВозвратТоваровОтКлиентаДополнительныеРеквизиты
		ПО (ЗаявкаНаВозвратТоваровОтКлиентаДополнительныеРеквизиты.Ссылка = ВЫРАЗИТЬ(NULL КАК Справочник.Назначения).Заказ)
			И (ЗаявкаНаВозвратТоваровОтКлиентаДополнительныеРеквизиты.Свойство = &П),
	(ВЫБРАТЬ
		0 КАК Поле1) КАК ВложенныйЗапрос1
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ЗаказКлиентаДополнительныеРеквизиты
		ПО (ЗаказКлиентаДополнительныеРеквизиты.Ссылка = ВЫРАЗИТЬ(NULL КАК Справочник.Назначения).Заказ)
			И (ЗаказКлиентаДополнительныеРеквизиты.Свойство = &П)

Конструкция ВЫРАЗИТЬ(NULL КАК Справочник.Назначения).Заказ — это пример того, как платформа 1С пытается создать синтаксически корректный, но логически запутанный запрос для унификации условий. Именно эта сложность и вводит в заблуждение оптимизатор SQL Server.

Решение: разделение дополнительных реквизитов

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

Разберем решение по шагам:

  1. Определите "проблемный" реквизит. Найдите тот самый дополнительный реквизит, который используется в отборе и назначен нескольким типам документов.
  2. Удалите назначение реквизита. Зайдите в настройку дополнительных реквизитов (раздел НСИ и администрирование -> Общие настройки -> Дополнительные реквизиты и сведения). Найдите ваш реквизит и уберите его назначение для того типа документа, который был добавлен последним и вызвал ошибку. Например, если реквизит изначально был для "Заказа клиента", а потом его добавили к "Заявке на возврат", то у "Заявки на возврат" это назначение нужно убрать.
  3. Создайте новый, уникальный реквизит. Для того типа документа, у которого вы убрали назначение, создайте новый дополнительный реквизит. Пусть у него будет такое же наименование для пользователя ("Своя дата доставки"), но в системе это будет уже другой, независимый объект.
  4. Проверьте работу обработки. После этих действий откройте обработку "Обеспечение потребностей" снова. Теперь, когда отбор будет строиться по реквизиту, принадлежащему только одному типу объектов, СКД сгенерирует простой и корректный SQL-запрос, и ошибка исчезнет.

Этот подход не только решает проблему с ошибкой, но и положительно сказывается на производительности системы, так как генерируемые запросы становятся значительно проще и быстрее выполняются на стороне СУБД.

Рекомендации на будущее

Таким образом, решением проблемы является не изменение кода конфигурации, а корректировка пользовательских настроек — разделение одного общего дополнительного реквизита на несколько уникальных для каждого типа документа.

← На главную