Как правильно удалить измерения из регистра сведений и избежать ошибок уникальности

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

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

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

Понимание механики процесса на уровне СУБД

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

  1. Создает временную таблицу в SQL с новой структурой (без удаляемых измерений).
  2. Переносит данные из основной таблицы регистра во временную.
  3. Пытается создать уникальный индекс по новому набору измерений.

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

Способ 1. Программная подготовка данных через «схлопывание» записей

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

Предположим, у нас есть регистр ЦеныНоменклатуры, и мы хотим удалить измерения ВидУпаковки и Склад. После их удаления записи должны остаться уникальными только в разрезе Номенклатура и ТипЦены.

Разберем алгоритм решения задачи:


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

РезультатЗапроса = Запрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();

// 2. Очищаем регистр и записываем новые "схлопнутые" данные.
// Важно: если данных очень много, запись нужно делать порциями!
НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
// В данном случае мы не устанавливаем отбор, так как хотим перезаписать весь регистр целиком
НаборЗаписей.Загрузить(ТаблицаДанных);
Попытка
    НаборЗаписей.Записать(Истина); // Флаг Истина означает полную замену данных
    Сообщить("Данные успешно подготовлены к реструктуризации.");
Исключение
    Сообщить("Ошибка при записи: " + ОписаниеОшибки());
КонецПопытки;

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

Способ 2. Использование инструментов автоматизации (DevTools)

Если вы не хотите писать код вручную, можно воспользоваться специализированными инструментами. Например, подсистема «Инструменты разработчика» содержит обработку «Подготовка к изменению структуры БД».

Рассмотрим порядок действий с этим инструментом:

  1. Запустите обработку и выберите нужный регистр сведений.
  2. Нажмите кнопку «Автокорректировка».
  3. Система проанализирует текущие данные и предложит варианты устранения дублей (обычно это удаление лишних записей с сохранением одной).
  4. После выполнения корректировки вы сможете спокойно удалить измерения в конфигураторе и обновить базу.

Способ 3. Перенос данных через временный регистр (для Highload-систем)

На огромных таблицах (десятки и сотни миллионов записей) метод с полной выгрузкой в ТаблицаЗначений может привести к переполнению оперативной памяти. В такой ситуации мы рекомендуем следующий «промышленный» подход:

  1. Создайте в конфигураторе новый регистр сведений (например, ЦеныНоменклатуры_Новый) с уже целевой структурой (без тех самых двух измерений).
  2. Напишите обработку, которая будет переносить данные из старого регистра в новый порциями по 50 000 – 100 000 записей.
  3. В процессе переноса используйте проверку: если запись с такими измерениями в новом регистре уже есть, решайте, нужно ли ее обновлять или пропустить.
  4. После завершения переноса удалите старый регистр в конфигураторе, а новый переименуйте, дав ему имя старого.

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

Важные нюансы и риски

Проанализируем дополнительные факторы, которые могут повлиять на результат:

Периодичность регистра

Если ваш регистр — периодический, помните, что поле Период технически является таким же измерением. Если вы удаляете другие измерения, то уникальность должна теперь соблюдаться в разрезе Период + ОставшиесяИзмерения. Если у вас было две записи на одну секунду, различавшиеся только удаляемыми измерениями — это гарантированный дубль.

Ведущие измерения

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

Ссылочная целостность

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

Резюме: Никогда не удаляйте измерения «в лоб», если в базе уже есть данные. Всегда делайте резервную копию и предварительно очищайте дубликаты программным способом, используя группировку в запросе.

← На главную