В процессе сопровождения и разработки в среде 1С:Предприятие 7.7 программисты часто сталкиваются с ситуацией, когда в справочниках появляются элементы с одинаковыми наименованиями. Это порождает закономерный вопрос: какой именно элемент выберет встроенный метод НайтиПоНаименованию(), если система обнаружит несколько подходящих записей? Разберем эту ситуацию подробно, опираясь на техническое устройство платформы и опыт экспертов.
Рассмотрим предположение о том, что система находит элемент с минимальным кодом. Проанализируем внутреннюю структуру хранения данных. В 1С 7.7 (особенно в версии для SQL) за поиск по наименованию отвечает индекс по полю DESCR. Однако этот индекс не состоит из одного лишь наименования. Чтобы обеспечить уникальность записей в индексе, платформа добавляет к нему внутренний идентификатор объекта — ID.
Важно понимать различие:
Выясним, как формируется SQL-запрос. В SQL-версии индекс для справочника по наименованию обычно выглядит как составное поле: DESCR + ID (и PARENID для иерархических справочников). Когда мы вызываем метод НайтиПоНаименованию(), платформа обращается к этому индексу. Поскольку записи внутри индекса отсортированы по возрастанию, при совпадении текстового значения DESCR система вернет ту запись, у которой значение ID будет наименьшим в лексикографическом порядке.
Так как ID выдаются системой последовательно по мере создания новых элементов, нахождение элемента с минимальным ID фактически означает выбор хронологически самого первого созданного элемента. Таким образом, утверждение о поиске по минимальному коду является неверным — поиск ориентируется на внутренний порядок в индексе базы данных.
Проанализируем поведение системы в файловом варианте. Здесь используются индексные файлы формата .cdx. Метод НайтиПоНаименованию() выполняет команду Seek по соответствующему индексу. Порядок следования идентичных наименований в файловом индексе также детерминирован и в большинстве случаев совпадает с физическим порядком создания записей. Однако стоит учитывать, что полагаться на этот порядок в долгосрочной перспективе опасно: после операций «Тестирования и исправления» с пересозданием объектов или после выгрузки/загрузки данных через текстовые файлы, внутренние ID могут измениться, и «первым» станет уже другой дубль.
Просто знать, как работает поиск — недостаточно. Если в базе данных есть дубли, это рано или поздно приведет к ошибкам в аналитике и отчетах. Разберем основные стратегии борьбы с дублями в «семерке».
1. Простое переименование
Самый быстрый, но «грязный» способ — переименовать ненужные дубли (например, добавить префикс «УДАЛИТЬ_» или «*»), чтобы метод НайтиПоНаименованию() их игнорировал. Однако это не решает проблему ссылочной целостности: в старых документах ссылки по-прежнему будут вести на разные элементы.
2. Программный поиск и замена ссылок
Это классический подход, который требует написания специальной обработки. Суть заключается в том, чтобы найти все упоминания «плохого» элемента во всех документах, справочниках и регистрах и заменить их на «хороший» (эталонный) элемент.
Посмотрим на алгоритм реализации такой замены:
Сложность с регистрами в 1С 7.7:
В отличие от 8-й версии платформы, в 1С 7.7 нельзя просто программно перезаписать движения регистра, не затрагивая сам документ. Движения в «клюшках» неразрывно связаны с модулем проведения документа.
Если в базе запрещены прямые SQL-запросы, а перепроведение документов невозможно из-за риска изменения итогов, программисты применяют хитрости. Разберем одну из таких методик:
Метод временной подмены модуля проведения:
Метод прямого обновления через SQL (для SQL-версий):
Если использование прямых запросов допустимо, задачу можно решить значительно быстрее. Рассмотрим пример логики:
// Пример логики прямого обновления (псевдокод SQL)
UPDATE [ТаблицаРегистра]
SET [ПолеНоменклатура] = 'ID_Эталона'
WHERE [ПолеНоменклатура] IN ('ID_Дубля1', 'ID_Дубля2');
UPDATE [ТаблицаШапкиДокумента]
SET [РеквизитСправочник] = 'ID_Эталона'
WHERE [РеквизитСправочник] IN ('ID_Дубля1', 'ID_Дубля2');
После выполнения таких операций обязательно требуется выполнить полный пересчет итогов в конфигураторе, чтобы данные в таблицах остатков и оборотов соответствовали новым ссылкам.
Проанализировав ситуацию, можно сделать следующие выводы:
НайтиПоНаименованию() в 1С 7.7 находит первый созданный элемент (с минимальным ID), что обусловлено структурой индексов.ID может измениться при определенных административных действиях.ИспользоватьРодителя() перед поиском, чтобы ограничить область выборки и снизить вероятность нахождения дубля из другой группы.Таким образом, системный подход к ведению справочников и регулярный аудит данных на наличие дублей — единственный способ обеспечить корректную работу метода НайтиПоНаименованию() и достоверность отчетов в системе 1С:Предприятие 7.7.