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