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