Как программно найти и удалить последнюю запись периодического регистра сведений в 1С?

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

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

В этой статье мы подробно разберем, как правильно вычислить последнюю запись и какими методами платформы 1С её можно удалить. Мы проанализируем использование менеджера записи, набора записей и оптимизацию через запросы.

Метод 1. Использование Менеджера записи и СрезПоследних

Самый простой и интуитивно понятный способ — это сначала определить дату последней записи, а затем использовать РегистрСведенийМенеджерЗаписи для её удаления. Рассмотрим этот процесс по шагам.

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

Шаг 1. Получаем период последней записи

Воспользуемся методом СрезПоследних, передав в него структуру отбора по интересующим нас измерениям.


// Определяем отбор по измерениям
Отбор = Новый Структура;
Отбор.Вставить("ВладелецСчета", ВладелецСчета);
Отбор.Вставить("БанковскийСчет", БанковскийСчет);

// Получаем таблицу с последней записью
ТаблицаПоследнейЗаписи = РегистрыСведений.МойРегистр.СрезПоследних(ТекущаяДата(), Отбор);

Если ТаблицаПоследнейЗаписи.Количество() > 0 Тогда
    // Получаем точный период из найденной записи
    НужныйПериод = ТаблицаПоследнейЗаписи[0].Период;
Иначе
    Возврат; // Записей нет, удалять нечего
КонецЕсли;

Шаг 2. Удаление записи через Менеджер записи

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


МЗ = РегистрыСведений.МойРегистр.СоздатьМенеджерЗаписи();
МЗ.ВладелецСчета = ВладелецСчета;
МЗ.БанковскийСчет = БанковскийСчет;
МЗ.Период = НужныйПериод;

// Перед удалением рекомендуется прочитать запись, чтобы убедиться в её существовании
МЗ.Прочитать();
Если МЗ.Выбран() Тогда
    МЗ.Удалить();
КонецЕсли;

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

Метод 2. Удаление через Набор записей

Использование объекта НаборЗаписей считается более «профессиональным» подходом, так как он работает быстрее при массовых операциях и позволяет избежать лишнего вызова Прочитать(). Выясним причину: набор записей позволяет наложить фильтр и просто перезаписать пустой набор, что фактически удаляет данные.

Рассмотрим пример реализации:


Набор = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();

// Устанавливаем фильтры (отборы) по измерениям и периоду
Набор.Отбор.ВладелецСчета.Установить(ВладелецСчета);
Набор.Отбор.БанковскийСчет.Установить(БанковскийСчет);
Набор.Отбор.Период.Установить(НужныйПериод);

// Записываем пустой набор с флагом замещения
// Это удалит все записи, попадающие под фильтр
Набор.Записать(Истина);

Преимущество этого метода в том, что если по какой-то причине (например, сбой при программном заполнении) в одну и ту же секунду/день попало несколько идентичных по измерениям записей, набор записей гарантированно очистит их все.

Метод 3. Оптимизация через запрос (для «тяжелых» регистров)

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

Проанализируем пример запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	МАКСИМУМ(МойРегистр.Период) КАК ПоследнийПериод
    |ИЗ
    |	РегистрСведений.МойРегистр КАК МойРегистр
    |ГДЕ
    |	МойРегистр.ВладелецСчета = &ВладелецСчета
    |	И МойРегистр.БанковскийСчет = &БанковскийСчет";

Запрос.УстановитьПараметр("ВладелецСчета", ВладелецСчета);
Запрос.УстановитьПараметр("БанковскийСчет", БанковскийСчет);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Если Выборка.Следующий() И ЗначениеЗаполнено(Выборка.ПоследнийПериод) Тогда
    // Теперь используем Выборка.ПоследнийПериод для удаления через МенеджерЗаписи
КонецЕсли;

Использование функции МАКСИМУМ(Период) в запросе — это самый быстрый способ получить дату последней активности в системе по конкретному объекту.

Особенности периодичности и транзакций

При решении задачи удаления записей необходимо учитывать два критических момента:

  1. Периодичность регистра. Если в конфигураторе для регистра установлена периодичность День, то время в поле Период всегда будет равно 00:00:00. Если же установлена периодичность Секунда, то при поиске и удалении крайне важно соблюдать точность до секунды. Ошибка в 1 секунду приведет к тому, что метод Прочитать() вернет ложь.
  2. Транзакционная целостность. В многопользовательской среде может возникнуть ситуация: вы получили период последней записи, но пока выполнялся код удаления, другой пользователь успел внести новую запись. В итоге вы удалите не ту запись или получите ошибку. Чтобы этого избежать, рекомендуется оборачивать процесс в транзакцию:
    
    НачатьТранзакцию();
    Попытка
        // Здесь код поиска периода и удаления
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        ЗаписьЖурналаРегистрации("УдалениеЗаписи", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
    КонецПопытки;
    

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

← На главную