При работе в среде 1С:Предприятие 8.3 разработчики часто сталкиваются с ситуацией, когда при открытии формы списка документов или справочников система выдает критическую ошибку: «Обнаружено дублирование ключевых значений в колонках "ссылка", отображение данных в списке невозможно». Эта проблема блокирует работу пользователя с объектом и требует вмешательства программиста. Проанализируем причины возникновения этой ошибки и разберем по шагам способы ее устранения.
Для начала выясним причину такого поведения платформы. Динамический список — это мощный инструмент, который считывает данные из базы порциями. Чтобы корректно отображать строки и понимать, какая строка соответствует какому объекту в базе, 1С использует уникальный идентификатор (UUID) — поле Ссылка. Если в результате выполнения запроса, который лежит в основе списка, на одну ссылку документа или справочника приходится две и более строки, платформа «теряется», так как не может определить, какую именно запись показывать. В этот момент и возникает ошибка дублирования ключей.
Часто начинающие разработчики совершают ошибку, пытаясь найти причину в модуле формы. Проанализируем ситуацию: если модуль формы пустой, это не значит, что запроса нет. Нам необходимо зайти в конфигуратор и открыть свойства динамического списка на форме.
ДинамическийСписок (обычно он называется Список).Именно здесь скрывается «сила», которая удваивает строки в результате запроса.
Рассмотрим подробнее самую частую причину — некорректное использование ЛЕВОЕ СОЕДИНЕНИЕ. Представим, что мы хотим вывести список товаров и рядом отобразить информацию о складах, на которых этот товар числится. Если товар лежит на трех складах, запрос вернет три строки с одинаковой ссылкой товара.
Пример проблемного запроса:
ВЫБРАТЬ
СправочникНоменклатура.Ссылка КАК Ссылка,
СправочникНоменклатура.Наименование КАК Наименование,
ОстаткиТоваров.Склад КАК Склад
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ОстаткиТоваров
ПО СправочникНоменклатура.Ссылка = ОстаткиТоваров.Номенклатура
В данном случае, если у одной номенклатуры есть остатки по нескольким складам, динамический список выдаст ошибку. Чтобы этого избежать, необходимо пересмотреть логику. Либо мы выводим только уникальные ссылки, либо используем агрегатные функции, чтобы схлопнуть данные до одной строки.
Если нам не важны дополнительные данные из присоединенных таблиц, а дубли возникают из-за самого факта соединения, простейшим решением будет добавление ключевого слова РАЗЛИЧНЫЕ (DISTINCT) в начало запроса.
ВЫБРАТЬ РАЗЛИЧНЫЕ
ДокументРеализация.Ссылка,
ДокументРеализация.Дата,
ДокументРеализация.Номер
ИЗ
Документ.РеализацияТоваровУслуг КАК ДокументРеализация
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыДокументов КАК Статусы
ПО ДокументРеализация.Ссылка = Статусы.Документ
Важный момент: помните, что РАЗЛИЧНЫЕ нельзя использовать, если в выборку включены поля неограниченной длины (например, многострочные комментарии или хранилища значений).
Проанализируем настройки самого динамического списка. У каждого списка есть свойство Основная таблица. Если она указана (например, Документ.РеализацияТоваровУслуг), платформа берет на себя часть работы по оптимизации запроса. Если же поле пустое, вам может потребоваться вручную указать ключевые поля в конструкторе запроса на закладке «Настройка списка».
Однако лучшей практикой считается всегда указывать основную таблицу, если список отображает данные одного типа. Это позволяет системе корректно работать со стандартными командами (создание, копирование, пометка на удаление) и уменьшает вероятность ошибки дублирования.
Если использование РАЗЛИЧНЫЕ невозможно или нецелесообразно, воспользуемся группировкой. Рассмотрим пример, когда нам нужно получить сумму по табличной части документа прямо в списке:
ВЫБРАТЬ
Реализация.Ссылка КАК Ссылка,
СУММА(РеализацияТовары.Сумма) КАК ОбщаяСумма
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ПО Реализация.Ссылка = РеализацияТовары.Ссылка
СГРУППИРОВАТЬ ПО
Реализация.Ссылка
Использование СГРУППИРОВАТЬ ПО гарантирует, что на каждый объект Ссылка будет сформирована ровно одна строка, что полностью исключает появление обсуждаемой ошибки.
Иногда ситуация выглядит странно: под полными правами список открывается, а у пользователя — ошибка. Выясним причину: в этом виноват механизм RLS (Record Level Security). Платформа динамически дописывает к вашему запросу условия ограничения прав. Если правила RLS настроены некорректно (например, через сложные соединения с другими таблицами), они могут приводить к размножению строк.
В этом случае необходимо проанализировать шаблоны ограничений в ролях пользователя и убедиться, что они не вносят деструктивных изменений в результирующую выборку.
Если вы уверены, что «в конфу не лазили», а ошибка появилась, обязательно проверьте наличие расширений. Расширение может перехватывать запрос динамического списка или добавлять свои условия. Попробуйте временно отключить расширения по одному, чтобы исключить их влияние. Даже если документ не участвует в расширении напрямую, расширение может накладывать общие фильтры или изменять поведение механизмов платформы.
В редких случаях проблема может быть вызвана повреждением локального кэша метаданных. Если после исправления запроса ошибка сохраняется у конкретного пользователя, выполните следующие действия:
1C:Enterprise Server.Также рекомендуется выполнить Тестирование и исправление в конфигураторе с включенными опциями «Реиндексация таблиц» и «Проверка логической целостности», чтобы исключить физическое дублирование записей на уровне СУБД.
Подводя итог, можно сказать, что ошибка дублирования ключей — это всегда сигнал о том, что запрос возвращает «лишние» данные. Тщательный анализ соединений и использование группировок позволяют решить эту проблему в 99% случаев.