При работе в программах на платформе 1С:Предприятие пользователи и администраторы периодически сталкиваются со специфической ошибкой: «Обнаружено дублирование ключевых значений в колонке "Ссылка"» (или аналогичной колонке, являющейся ключевой для списка). Самое загадочное в этой ситуации — часто ошибка воспроизводится только у одного конкретного пользователя, в то время как у остальных коллег справочник или документ открывается абсолютно нормально. Более того, после закрытия окна с ошибкой список данных всё-таки отображается.
В этой статье мы подробно разберем природу этого явления, выясним, почему в сбое виноваты индивидуальные настройки интерфейса, и рассмотрим по шагам методы решения проблемы как со стороны системного администратора, так и со стороны разработчика 1С.
Для начала проанализируем, как работает динамический список в 1С. Этот объект оптимизирован для быстрого, порционного считывания информации из базы данных. Если у динамического списка заполнено свойство ОсновнаяТаблица (например, указан справочник Справочник.Контрагенты), платформа жестко контролирует уникальность записей по ключевому полю Ссылка. Система ожидает, что в выборке не может быть двух строк с одинаковым уникальным идентификатором ссылки.
Если в результате выполнения запроса динамического списка (с учетом всех наложенных отборов, группировок и присоединенных таблиц) в выборку попадают две или более строки с одинаковым значением в колонке Ссылка, внутренние механизмы платформы не могут сопоставить эти данные для вывода на экран. Происходит конфликт адресации строк, и система выдает предупреждение о дублировании ключевых значений.
Теперь ответим на вопрос, почему это происходит только у одного пользователя. Все дело в механизме пользовательских настроек компоновки данных. Платформа 1С позволяет каждому пользователю индивидуально настраивать списки под себя:
Еще — Изменить форму пользователь может самостоятельно вывести на экран колонку, содержащую множественные свойства. Например, если у одного контрагента в базе заведено два номера телефона или два адреса электронной почты, левое соединение с таблицей контактной информации в запросе динамического списка вернет две строки для одного контрагента. Ссылка одна — строк две. Вот и причина дублирования.Давайте разберем по шагам, как локализовать и устранить эту проблему.
Самый быстрый способ вернуть форму в рабочее состояние — сбросить все индивидуальные настройки, которые пользователь успел применить к этому списку. Начнем с простейшего действия непосредственно в интерфейсе проблемного сеанса.
Попросим пользователя открыть форму списка (например, справочника «Контрагенты»). После появления и закрытия окна с ошибкой выполним следующие действия:
Если этот вариант не помог или форма из-за ошибки ведет себя некорректно, администратор может принудительно очистить настройки данного пользователя через стандартные механизмы базы данных. Рассмотрим, как это сделать:
После этой процедуры форма гарантированно откроется с дефолтными настройками, спроектированными разработчиком конфигурации, и ошибка исчезнет.
Если сброс настроек помогает лишь временно, а при попытке снова вывести, к примеру, адреса или телефоны ошибка возвращается, необходимо проверить целостность самих данных в базе. Зачастую динамический список обращается левым соединением к регистрам сведений (например, к регистру контактной информации или регистру дополнительных сведений).
Проанализируем ситуацию: в регистре сведений по одному и тому же контрагенту из-за сбоя при переносе данных, некорректной синхронизации или работы сторонних обработок могли образоваться дублирующие записи. Например, в регистре сведений по контактной информации для одного контрагента записаны две строки с одинаковым типом и видом контакта. При выполнении левого соединения платформа получит две записи, что приведет к дублированию ключевого поля Ссылка в динамическом списке.
Для решения этой проблемы необходимо найти дублирующиеся записи в связанных регистрах сведений (через функции для технического специалиста или консоль запросов) и физически удалить лишние строки, восстановив логическую целостность данных.
Если вы являетесь разработчиком конфигурации и хотите полностью исключить появление подобной ошибки у пользователей в будущем, вам необходимо доработать сам запрос динамического списка. Посмотрим на этот процесс по шагам.
Сначала нам нужно понять, какие именно данные вызывают сбой. Для этого выполним отладку запроса:
ПриСозданииНаСервере. Нам нужно поймать момент после окончательного формирования структуры списка.Список.ТекстЗапроса и скопируем его текст. Также не забудем проверить коллекцию Список.Параметры, если в запросе используются внешние параметры.
ВЫБРАТЬ
ВложенныйЗапрос.Ссылка КАК ПроблемнаяСсылка,
КОЛИЧЕСТВО(ВложенныйЗапрос.Ссылка) КАК КоличествоСтрок
ИЗ
(
// Сюда вставляем скопированный текст запроса динамического списка
ВЫБРАТЬ
Контрагенты.Ссылка КАК Ссылка,
Контрагенты.Наименование КАК Наименование
ИЗ
Справочник.Контрагенты КАК Контрагенты
) КАК ВложенныйЗапрос
СГРУППИРОВАТЬ ПО
ВложенныйЗапрос.Ссылка
ИМЕЮЩИЕ
КОЛИЧЕСТВО(ВложенныйЗапрос.Ссылка) > 1
Выполнив этот запрос, мы сразу увидим список ссылок на элементы справочника, которые дублируются в выборке, а также точное количество их дублей. Теперь проанализируем структуру связей в самом запросе списка.
Как правило, дублирование возникает из-за конструкции ЛЕВОЕ СОЕДИНЕНИЕ. Рассмотрим пример некорректного соединения:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Ссылка,
Контрагенты.Наименование КАК Наименование,
Контакты.Представление КАК Телефон
ИЗ
Справочник.Контрагенты КАК Контрагенты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК Контакты
ПО Контрагенты.Ссылка = Контакты.Объект
В данном случае, если у контрагента заполнено несколько видов контактной информации (и телефон, и адрес, и email), левое соединение сопоставит контрагенту каждую из этих записей. На выходе мы получим несколько строк с одной и той же ссылкой контрагента.
Чтобы исправить этот запрос в Конфигураторе, нам необходимо наложить жесткие ограничения на выбираемые данные из подчиненной таблицы, гарантируя получение строго одной строки. Перепишем запрос следующим образом:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Ссылка,
Контрагенты.Наименование КАК Наименование,
Контакты.Представление КАК Телефон
ИЗ
Справочник.Контрагенты КАК Контрагенты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК Контакты
ПО Контрагенты.Ссылка = Контакты.Объект
И Контакты.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон)
И Контакты.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтрагента)
Указав конкретный тип и вид контактной информации в условии связи, мы гарантируем, что для каждого контрагента соединение вернет максимум одну строку, и дублирование ключевого поля Ссылка будет полностью исключено.
Также в практике разработки полезно использовать следующие приемы защиты от дублирования:
ВЫБРАТЬ РАЗЛИЧНЫЕ на самом верхнем уровне пакета запроса помогает схлопнуть идентичные строки. Однако помните, что это может незначительно снизить производительность динамического списка на больших объемах данных.Основная таблица. После этого платформа перестанет отслеживать уникальность поля Ссылка, и ошибка дублирования ключевых значений гарантированно исчезнет, хотя список станет доступен только в режиме просмотра.Мы подробно разобрали все грани проблемы с дублированием ключевых значений в динамических списках 1С. Применяя описанные методы сброса настроек и корректировки связей в запросах, вы сможете быстро и профессионально устранять подобные сбои в работе пользователей.