Как исправить ошибку "Обнаружено дублирование ключевых значений в колонке ссылка" в динамическом списке 1С?

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

При доработке форм в 1С, особенно форм списков, разработчики часто сталкиваются с ошибкой: «Обнаружено дублирование ключевых значений в колонке ссылка. Отображение данных в списке невозможно». Обычно она возникает после изменения запроса динамического списка, например, при добавлении новой колонки через соединение с другой таблицей. Давайте подробно разберем, почему эта ошибка появляется и какие существуют способы ее исправления.

Понимаем причину ошибки

В основе работы динамического списка лежит запрос, который получает данные для отображения. У каждого динамического списка есть свойство «Основная таблица». Платформа 1С требует, чтобы для каждой строки, возвращаемой запросом, значение в ключевом поле (по умолчанию это поле Ссылка основной таблицы) было уникальным. Это необходимо для корректной работы стандартных механизмов формы: позиционирования, открытия элемента, работы командной панели (создание, удаление, копирование) и т.д.

Ошибка возникает, когда вы соединяете (чаще всего через ЛЕВОЕ СОЕДИНЕНИЕ) основную таблицу с другой таблицей, в которой одной записи из основной таблицы соответствует несколько записей. В результате запроса строки основной таблицы "размножаются", и в итоговой выборке появляется несколько строк с одним и тем же значением в поле Ссылка.

Проанализируем классический пример. Мы хотим добавить цену в список номенклатуры. Основная таблица — Справочник.Номенклатура.

Вот исходный запрос, который вызывает ошибку:


ВЫБРАТЬ
    СпрНоменклатура.Ссылка КАК Ссылка,
    СпрНоменклатура.Код КАК Код,
    СпрНоменклатура.Наименование КАК Наименование,
    ЦеныНоменклатурыСрезПоследних.Цена
ИЗ
    Справочник.Номенклатура КАК СпрНоменклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ) КАК ЦеныНоменклатурыСрезПоследних
        ПО ЦеныНоменклатурыСрезПоследних.Номенклатура = СпрНоменклатура.Ссылка
ГДЕ
    НЕ СпрНоменклатура.ЭтоГруппа

Проблема здесь в том, что у одной позиции номенклатуры может быть установлено несколько видов цен (например, "Оптовая", "Розничная", "Закупочная"). Виртуальная таблица ЦеныНоменклатуры.СрезПоследних без указания фильтра по виду цены вернет все актуальные цены для каждой номенклатуры. Если для товара "Стол" есть оптовая и розничная цена, то в результате запроса для ссылки на этот товар будет две строки, что и вызывает ошибку.

Решение 1: Фильтрация данных в присоединяемой таблице

Самый правильный и распространенный способ решения — это изменить запрос так, чтобы он возвращал только одну запись из присоединяемой таблицы для каждой записи основной.

В нашем примере с ценами нужно указать, какой именно вид цены мы хотим видеть в списке. Для этого в параметры виртуальной таблицы СрезПоследних добавим условие отбора.

Шаги для исправления:

  1. Определите, какой именно вид цены нужен. Часто это какой-то основной вид цен, который можно либо жестко задать в запросе, либо вынести в параметр формы.
  2. Добавьте условие в параметры виртуальной таблицы.

Исправленный запрос будет выглядеть так:


ВЫБРАТЬ
    СпрНоменклатура.Ссылка КАК Ссылка,
    СпрНоменклатура.Код КАК Код,
    СпрНоменклатура.Наименование КАК Наименование,
    ЦеныНоменклатурыСрезПоследних.Цена
ИЗ
    Справочник.Номенклатура КАК СпрНоменклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, <strong>ВидЦены = &ВидЦены</strong>) КАК ЦеныНоменклатурыСрезПоследних
        ПО ЦеныНоменклатурыСрезПоследних.Номенклатура = СпрНоменклатура.Ссылка
ГДЕ
    НЕ СпрНоменклатура.ЭтоГруппа

Теперь для каждой номенклатуры будет выбрана цена только одного, указанного в параметре &ВидЦены, вида. Это гарантирует, что соединение не создаст дубликатов, и ошибка исчезнет.

Решение 2: Исправление некорректных данных в базе

Иногда причина кроется не в логике запроса, а в самих данных. Дублирующиеся записи могут появляться в регистрах или даже справочниках после некорректных обменов, обновлений конфигурации или ручной загрузки данных. В таких случаях правка запроса может не помочь или быть лишь временной "заплаткой".

Пример из практики (ЗУП 3.1):

После обновления конфигурации ЗУП пользователи стали получать ошибку дублирования ключей при открытии списка сотрудников. Диагностика показала, что основная таблица списка Справочник.Сотрудники соединяется с регистром сведений Текущие кадровые данные сотрудников для вывода информации о текущем месте работы.

Оказалось, что в процессе обновления в этом регистре для некоторых сотрудников образовались дублирующиеся записи. Например, две записи о приеме на работу. Из-за этого запрос динамического списка возвращал две строки для одного сотрудника, что приводило к ошибке.

Как действовать в такой ситуации:

  1. Диагностика. Скопируйте текст запроса из динамического списка и выполните его в консоли запросов. Найдите, для каких ссылок появляются дубли.
  2. Анализ данных. Проанализируйте данные в присоединенных таблицах для этих "проблемных" ссылок. Выясните, почему для них возвращается несколько записей.
  3. Очистка данных. Если вы обнаружили некорректные дубли, их необходимо удалить. Это можно сделать с помощью специальных обработок (например, "Универсальный подбор и обработка объектов") или написать небольшой скрипт для удаления лишних записей регистра сведений.

Похожие ситуации встречаются и в других конфигурациях:

Решение 3: Общие модификации запроса

Если фильтрация по конкретному значению не подходит, можно использовать другие приемы языка запросов.

Использование ВЫБРАТЬ РАЗЛИЧНЫЕ

Первое, что часто приходит в голову, — добавить ключевое слово РАЗЛИЧНЫЕ в начало запроса. Иногда это помогает.


ВЫБРАТЬ РАЗЛИЧНЫЕ
    СпрНоменклатура.Ссылка КАК Ссылка,
    ...

Важно понимать ограничение: РАЗЛИЧНЫЕ удаляет только полностью идентичные строки. Если у вас для одной номенклатуры вернулось две строки, которые отличаются хотя бы одним полем (например, ценой: 100 руб. и 120 руб.), то обе строки останутся в результате, и ошибка не исчезнет.

Использование агрегатных функций и группировки

Более надежный способ — использовать вложенный запрос с группировкой и агрегатными функциями (МАКСИМУМ(), МИНИМУМ(), КОЛИЧЕСТВО() и т.д.), чтобы "свернуть" несколько записей в одну перед соединением.

Например, если нам не важен вид цены, а нужна просто максимальная цена из всех установленных:


ВЫБРАТЬ
    СпрНоменклатура.Ссылка КАК Ссылка,
    СпрНоменклатура.Наименование КАК Наименование,
    ЦеноваяИнформация.МаксЦена
ИЗ
    Справочник.Номенклатура КАК СпрНоменклатура
        ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
            Цены.Номенклатура КАК Номенклатура,
            МАКСИМУМ(Цены.Цена) КАК МаксЦена
        ИЗ
            РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ) КАК Цены
        СГРУППИРОВАТЬ ПО
            Цены.Номенклатура) КАК ЦеноваяИнформация
        ПО СпрНоменклатура.Ссылка = ЦеноваяИнформация.Номенклатура

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

Решение 4: Альтернативные и административные методы

В некоторых случаях проблему можно решить без изменения кода.

Очистка пользовательских настроек

Иногда ошибка возникает у конкретного пользователя из-за сохраненных, но уже неактуальных настроек формы (например, после обновления). В этом случае может помочь очистка настроек.

Путь в интерфейсе: Администрирование – Настройки пользователей и прав – Пользователи – (выбрать пользователя) – Очистка настроек. Это более радикальный способ. Можно попробовать сначала сбросить настройки конкретной формы через меню "Ещё" – "Установить стандартные настройки".

Отключение проверки на уникальность (не рекомендуется)

Есть "силовой" метод, который отключает саму проверку. В свойствах динамического списка нужно очистить поле «Основная таблица». После этого платформа перестанет контролировать уникальность ключевых полей, и ошибка исчезнет. Вы сможете вывести список с разными ценами для одной номенклатуры.

Внимание! У этого способа есть серьезные побочные эффекты:

Использовать этот метод стоит только в крайних случаях, когда вы полностью контролируете функционал формы и готовы реализовать всю необходимую логику вручную.

Таким образом, ошибка дублирования ключей — это сигнал о том, что логика вашего запроса не соответствует требованиям динамического списка. Лучший подход — найти причину "размножения" строк и скорректировать запрос или данные, чтобы обеспечить уникальность ключевого поля для каждой выводимой строки.

← На главную