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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

В этой статье мы подробно разберем природу этого явления, выясним, почему в сбое виноваты индивидуальные настройки интерфейса, и рассмотрим по шагам методы решения проблемы как со стороны системного администратора, так и со стороны разработчика 1С.

Почему возникает ошибка и почему она проявляется избирательно?

Для начала проанализируем, как работает динамический список в 1С. Этот объект оптимизирован для быстрого, порционного считывания информации из базы данных. Если у динамического списка заполнено свойство ОсновнаяТаблица (например, указан справочник Справочник.Контрагенты), платформа жестко контролирует уникальность записей по ключевому полю Ссылка. Система ожидает, что в выборке не может быть двух строк с одинаковым уникальным идентификатором ссылки.

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

Теперь ответим на вопрос, почему это происходит только у одного пользователя. Все дело в механизме пользовательских настроек компоновки данных. Платформа 1С позволяет каждому пользователю индивидуально настраивать списки под себя:

  1. Вывод дополнительных реквизитов или контактной информации: Через меню Еще — Изменить форму пользователь может самостоятельно вывести на экран колонку, содержащую множественные свойства. Например, если у одного контрагента в базе заведено два номера телефона или два адреса электронной почты, левое соединение с таблицей контактной информации в запросе динамического списка вернет две строки для одного контрагента. Ссылка одна — строк две. Вот и причина дублирования.
  2. Настройка сложных отборов и группировок: Пользователь мог самостоятельно настроить группировку списка по какому-то реквизиту или установить отбор, который привел к неявной перестройке SQL-запроса платформой. При определенном сочетании метаданных генератор запросов строит некорректное соединение (subquery), удваивающее строки.
  3. Конфликт программных и ручных настроек: Разработчик мог заложить в динамический список программный фильтр, а пользователь наложил свой собственный, который пересекается или конфликтует с программным, вызывая дублирование записей при связи таблиц.

Давайте разберем по шагам, как локализовать и устранить эту проблему.

Способ 1. Сброс настроек формы (Решение для администратора и пользователя)

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

Попросим пользователя открыть форму списка (например, справочника «Контрагенты»). После появления и закрытия окна с ошибкой выполним следующие действия:

  1. Нажмем кнопку Еще в правом верхнем углу списка.
  2. Выберем пункт меню Установить стандартные настройки.

Если этот вариант не помог или форма из-за ошибки ведет себя некорректно, администратор может принудительно очистить настройки данного пользователя через стандартные механизмы базы данных. Рассмотрим, как это сделать:

  1. Перейдем в раздел Администрирование (или НСИ и администрирование).
  2. Откроем пункт Настройки пользователей и прав, затем перейдем по ссылке Очистка настроек (в некоторых конфигурациях этот функционал доступен прямо из карточки пользователя в справочнике «Пользователи» на вкладке «Настройки»).
  3. В открывшемся окне выберем проблемного пользователя.
  4. Найдем в дереве настроек форму списка нужного объекта (в нашем примере — форму списка справочника «Контрагенты»). Обычно данные настройки хранятся в ветке «Настройки внешнего вида» или «Настройки отчетов и форм».
  5. Выделим нужную форму и нажмем кнопку Очистить.

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

Способ 2. Поиск дубликатов в связанных регистрах (Анализ данных)

Если сброс настроек помогает лишь временно, а при попытке снова вывести, к примеру, адреса или телефоны ошибка возвращается, необходимо проверить целостность самих данных в базе. Зачастую динамический список обращается левым соединением к регистрам сведений (например, к регистру контактной информации или регистру дополнительных сведений).

Проанализируем ситуацию: в регистре сведений по одному и тому же контрагенту из-за сбоя при переносе данных, некорректной синхронизации или работы сторонних обработок могли образоваться дублирующие записи. Например, в регистре сведений по контактной информации для одного контрагента записаны две строки с одинаковым типом и видом контакта. При выполнении левого соединения платформа получит две записи, что приведет к дублированию ключевого поля Ссылка в динамическом списке.

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

Способ 3. Диагностика и исправление запроса динамического списка (Решение для разработчика)

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

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

  1. Запустим базу в режиме отладки и установим точку останова в модуле формы списка контрагентов в процедуре ПриСозданииНаСервере. Нам нужно поймать момент после окончательного формирования структуры списка.
  2. В табло отладчика вычислим выражение Список.ТекстЗапроса и скопируем его текст. Также не забудем проверить коллекцию Список.Параметры, если в запросе используются внешние параметры.
  3. Откроем «Консоль запросов» и вставим туда скопированный текст. Чтобы быстро локализовать элементы, которые дублируются при соединении таблиц, напишем вспомогательный запрос. Обернем исходный текст запроса во вложенный запрос и выполним группировку по ключевому полю:

ВЫБРАТЬ
    ВложенныйЗапрос.Ссылка КАК ПроблемнаяСсылка,
    КОЛИЧЕСТВО(ВложенныйЗапрос.Ссылка) КАК КоличествоСтрок
ИЗ
    (
        // Сюда вставляем скопированный текст запроса динамического списка
        ВЫБРАТЬ
            Контрагенты.Ссылка КАК Ссылка,
            Контрагенты.Наименование КАК Наименование
        ИЗ
            Справочник.Контрагенты КАК Контрагенты
    ) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
    ВложенныйЗапрос.Ссылка

ИМЕЮЩИЕ
    КОЛИЧЕСТВО(ВложенныйЗапрос.Ссылка) > 1

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

Как правило, дублирование возникает из-за конструкции ЛЕВОЕ СОЕДИНЕНИЕ. Рассмотрим пример некорректного соединения:


ВЫБРАТЬ
    Контрагенты.Ссылка КАК Ссылка,
    Контрагенты.Наименование КАК Наименование,
    Контакты.Представление КАК Телефон
ИЗ
    Справочник.Контрагенты КАК Контрагенты
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК Контакты
        ПО Контрагенты.Ссылка = Контакты.Объект

В данном случае, если у контрагента заполнено несколько видов контактной информации (и телефон, и адрес, и email), левое соединение сопоставит контрагенту каждую из этих записей. На выходе мы получим несколько строк с одной и той же ссылкой контрагента.

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


ВЫБРАТЬ
    Контрагенты.Ссылка КАК Ссылка,
    Контрагенты.Наименование КАК Наименование,
    Контакты.Представление КАК Телефон
ИЗ
    Справочник.Контрагенты КАК Контрагенты
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК Контакты
        ПО Контрагенты.Ссылка = Контакты.Объект
        И Контакты.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон)
        И Контакты.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтрагента)

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

Также в практике разработки полезно использовать следующие приемы защиты от дублирования:

Мы подробно разобрали все грани проблемы с дублированием ключевых значений в динамических списках 1С. Применяя описанные методы сброса настроек и корректировки связей в запросах, вы сможете быстро и профессионально устранять подобные сбои в работе пользователей.

← На главную