Регистр сведений в режиме «Независимый»: свойства, запись, запросы
Содержание
Независимый регистр сведений
в 1С — это регистр, у которого свойство «Режим записи» равно Независимый. Записи в него попадают не при проведении документа, а напрямую: пользователь вводит их в форме списка, а программист пишет через НаборЗаписей или МенеджерЗаписи. У записи нет поля Регистратор, а уникальность держится на паре «период + измерения».
Типичная ситуация: разработчику нужно хранить курс валюты на дату, штрихкод товара или настройку по организации. Документа-основания нет, «проводить» нечего, а история значений нужна. Это и есть работа для независимого регистра сведений: что он из себя представляет, как его настроить и как с ним работать без потерь в производительности — разберём по шагам.
Чем независимый регистр сведений отличается от подчинённого регистратору
Режим записи выбирается на закладке «Данные» свойств регистра. Вариантов два, и от выбора зависит почти всё поведение объекта.
| Признак | Независимый | Подчинение регистратору |
|---|---|---|
| Кто создаёт записи | Пользователь или код напрямую | Документ-регистратор при проведении |
Поля Регистратор, НомерСтроки | Нет | Есть |
| Ввод в форме списка | Можно добавлять и править | Только просмотр |
| Удаление записей | Вручную или кодом | При отмене проведения или перепроведении |
| Периодичность «По позиции регистратора» | Недоступна | Доступна |
| Объект для одной записи | МенеджерЗаписи | Нет, только набор |
| Ключ записи | Период + все измерения | Регистратор + номер строки (плюс контроль уникальности по периоду и измерениям) |
Ещё одно отличие касается контроля. В подчинённом регистре правильность данных обеспечивает алгоритм проведения: перепровели документ — записи пересоздались. В независимом регистре такой страховки нет. Кто последним записал строку, тот и прав, поэтому проверки заполнения и права на изменение приходится продумывать отдельно: в модуле набора записей (ПередЗаписью) и в ролях.
Главное практическое следствие: в независимом регистре одна запись на каждое сочетание периода и измерений. Попытка записать вторую с тем же ключом без замещения вызовет ошибку. В подчинённом регистре записи «принадлежат» документу и живут вместе с ним.
Если сомневаетесь, какой режим выбрать, задайте вопрос: «Кто отвечает за появление записи?» Документ — подчинённый. Человек, обработка, загрузка из внешнего источника — независимый.
Как настроить независимый регистр сведений в конфигураторе
Регистр создают в ветке Регистры сведений дерева конфигурации. Свойства, которые влияют на работу больше всего:
- Режим записи (закладка «Данные») —
Независимый. - Периодичность:
Непериодический,В пределах секунды,В пределах дня,В пределах месяца,В пределах квартала,В пределах года. Для периодического регистра платформа добавляет полеПериоди приводит дату к началу интервала. Запишите курс на 15:30 при периодичности «день» — сохранится начало дня. - Измерения — ключ записи. У каждого измерения есть флаги:
- 🔑 «Основной отбор» — измерение попадёт в отбор набора записей и в обмен по отбору;
- 🔗 «Ведущее» — для ссылочного типа: при удалении объекта его записи в регистре удаляются, а в форме объекта можно открыть связанные записи;
- 🚫 «Запрет незаполненных значений» — пустое значение не запишется.
- Ресурсы — хранимые значения (курс, цена, признак).
- Реквизиты — дополнительные сведения к записи (комментарий, автор изменения).
- Итоги среза — у периодических регистров есть флаги «Разрешить итоги среза первых» и «Разрешить итоги среза последних» (подробнее — в разделе про производительность).
На закладке «Формы» задают форму списка и форму записи. Форма записи у независимого регистра работает с МенеджерЗаписи: пользователь открывает одну строку, правит её и сохраняет.
Смена периодичности или режима записи на заполненном регистре приводит к реструктуризации таблицы. Делайте это на копии базы и проверяйте, что ключи не схлопнутся: при переходе с «дня» на «месяц» несколько записей одного месяца сольются в одну.
Независимые регистры сведений в типовых конфигурациях и в своих доработках
В типовых решениях на базе БСП независимых регистров много. Несколько знакомых примеров:
- 💱 КурсыВалют — периодический «в пределах дня», измерение
Валюта, ресурсыКурсиКратность. Загружается обработкой с сайта ЦБ или вводится вручную. - 🏷️ ШтрихкодыНоменклатуры в УТ 11 — непериодический, одна запись на штрихкод.
- 🗂️ ВерсииОбъектов (БСП) — хранит сохранённые версии документов и справочников.
В своих доработках независимый регистр подходит, когда нужно:
- хранить соответствие «объект → значение» без реквизита в справочнике (не трогая типовой объект — удобно в расширении);
- вести историю значения по датам: тариф, норматив, ставку, ответственного;
- складывать результат загрузки из внешней системы с ключом по внешнему идентификатору;
- хранить технические флаги: «объект выгружен», «письмо отправлено», дату последней обработки.
Для «складских» данных с приходом и расходом независимый регистр сведений не годится — там нужен регистр накопления.
Как читать данные регистра запросом
Таблица и виртуальные таблицы
В запросе доступна основная таблица РегистрСведений.Имя и у периодических регистров две виртуальные таблицы:
СрезПоследних(Период, Условие)— последняя запись по каждому сочетанию измерений на дату (включительно);СрезПервых(Период, Условие)— первая запись начиная с даты.
Курсы валют на дату:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Курсы.Валюта,
| Курсы.Курс,
| Курсы.Кратность
|ИЗ
| РегистрСведений.КурсыВалют.СрезПоследних(&Дата, Валюта В (&Валюты)) КАК Курсы";
Запрос.УстановитьПараметр("Дата", НачалоДня(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("Валюты", МассивВалют);
Выборка = Запрос.Выполнить().Выбрать();
Отбор по измерениям пишите в параметре Условие виртуальной таблицы, а не в ГДЕ. Платформа применит его внутри подзапроса среза, и СУБД не будет считать срез по всем валютам ради одной.
Срез на дату каждого документа
СрезПоследних принимает одну дату. Когда нужен курс на дату каждого документа, используют группировку по максимальному периоду:
"ВЫБРАТЬ
| Док.Ссылка КАК Документ,
| Док.ВалютаДокумента КАК Валюта,
| МАКСИМУМ(Курсы.Период) КАК Период
|ПОМЕСТИТЬ ВТ_Периоды
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Док
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК Курсы
| ПО Курсы.Валюта = Док.ВалютаДокумента
| И Курсы.Период <= Док.Дата
|ГДЕ
| Док.Дата МЕЖДУ &Начало И &Конец
|СГРУППИРОВАТЬ ПО
| Док.Ссылка,
| Док.ВалютаДокумента
|;
|ВЫБРАТЬ
| ВТ.Документ,
| Курсы.Курс,
| Курсы.Кратность
|ИЗ
| ВТ_Периоды КАК ВТ
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК Курсы
| ПО ВТ.Валюта = Курсы.Валюта
| И ВТ.Период = Курсы.Период"
Первый пакет находит для каждого документа дату последнего курса, второй достаёт сам курс по точному ключу. Связка по периоду и измерению попадает в индекс регистра, поэтому запрос остаётся быстрым и на больших объёмах.
Запись, изменение и удаление из встроенного языка
У независимого регистра два инструмента записи. Выбор зависит от того, сколько строк вы меняете.
| Инструмент | Когда | Что учесть |
|---|---|---|
МенеджерЗаписи | Одна запись по полному ключу | Записать(Ложь) упадёт, если запись с таким ключом уже есть |
НаборЗаписей | Пакет записей по отбору | Без отбора замещение очистит весь регистр |
Одна запись: менеджер записи
МЗ = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();
МЗ.Период = НачалоДня(ТекущаяДатаСеанса());
МЗ.Валюта = Валюта;
МЗ.Курс = 92.5;
МЗ.Кратность = 1;
МЗ.Записать(); // по умолчанию Замещать = Истина
Чтобы прочитать существующую запись, заполните ключевые поля и вызовите МЗ.Прочитать(). Метод МЗ.Выбран() вернёт Истина, если запись нашлась. Удаление — МЗ.Удалить() после заполнения ключа.
Пакет записей: набор с отбором
Набор = РегистрыСведений.ШтрихкодыНоменклатуры.СоздатьНаборЗаписей();
Набор.Отбор.Штрихкод.Установить(Штрихкод);
Набор.Прочитать();
Если Набор.Количество() = 0 Тогда
Запись = Набор.Добавить();
Запись.Штрихкод = Штрихкод;
Иначе
Запись = Набор[0];
КонецЕсли;
Запись.Номенклатура = Номенклатура;
Набор.Записать(); // заменит записи, попадающие под отбор
Чтобы удалить записи по отбору, установите отбор и запишите пустой набор: Набор.Записать() без строк сотрёт всё, что под него попадает.
Набор без установленного отбора при записи с замещением удаляет все записи регистра. Перед Записать() проверяйте, что отбор установлен. Эта ошибка в обработке загрузки — самый частый способ потерять справочные данные целиком.
Блокировки при параллельной записи
Если два сеанса могут писать один ключ одновременно (фоновые загрузки, обмены), читайте и пишите внутри транзакции с управляемой блокировкой:
НачатьТранзакцию();
Попытка
Блокировка = Новый БлокировкаДанных;
Элемент = Блокировка.Добавить("РегистрСведений.ШтрихкодыНоменклатуры");
Элемент.УстановитьЗначение("Штрихкод", Штрихкод);
Элемент.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
// чтение набора, изменение и запись — как в примере выше
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Без блокировки два сеанса прочитают «записи нет», оба добавят строку, и второй получит ошибку уникальности ключа.
Производительность и индексация независимого регистра
Платформа сама строит индексы по ключу записи: Период (у периодических) и измерения в том порядке, в котором они стоят в дереве конфигурации. Отсюда несколько приёмов.
Порядок измерений
Первым ставьте измерение, по которому отбирают чаще всего. Если регистр почти всегда читают по Организация, а потом по Номенклатура, такой порядок и нужен. Отбор только по второму измерению начальную часть индекса не использует.
Индексы по ресурсам и реквизитам
Ресурсы и реквизиты по умолчанию не индексируются. Если по ресурсу ищут (например, по внешнему коду), включите у него свойство «Индексировать». Лишние индексы замедляют запись, поэтому включайте их только под реальные запросы.
Итоги среза
Флаги «Разрешить итоги среза последних» и «Разрешить итоги среза первых» заставляют платформу хранить отдельную таблицу с актуальным срезом. Она ускоряет СрезПоследних без даты или с датой не раньше последней записи — типичный случай «текущая цена, текущий курс».
Цена — дополнительная работа при каждой записи. Для регистров с частой записью и редким чтением итоги среза скорее вредны. Если таблица итогов разошлась с данными, её пересчитывают из кода (РегистрыСведений.Имя.ПересчитатьИтоги()) или через «Тестирование и исправление» в конфигураторе.
«Тестирование и исправление» требует монопольного доступа: пользователи должны выйти из базы. Запускайте его вне рабочего времени и после резервной копии.
Частые записи по одной строке
Цикл с МенеджерЗаписи.Записать() на тысячи строк — это тысячи отдельных обращений к СУБД. Если ключи можно сгруппировать под один отбор, пишите набором: одна запись набора вместо тысячи мелких.
Типичные ошибки разработчика
Частые вопросы
Можно ли перевести независимый регистр в подчинённый регистратору?
Есть ли у независимого регистра сведений поле «Активность»?
Активность есть только у регистров, подчинённых регистратору.