К статье
Практический материал

Разработка и Конфигурация · 11 мин

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

Как получить запись регистра сведений в 1С: через менеджер записи, запрос, срез последних. Примеры кода, проверка результата и типичные ошибки разработчика.

Регистр сведений — один из самых востребованных объектов конфигурации: в нём хранятся цены, курсы валют, адреса, настройки и другие данные, привязанные к измерениям и, при необходимости, к периоду. Задача «получить запись» возникает постоянно: прочитать текущую цену товара, найти адрес контрагента, проверить, существует ли запись с нужным ключом.

В 1С есть несколько способов получить запись регистра сведений: через менеджер записи, через запрос, через срез последних или первых. У каждого способа своя скорость, свои ограничения и сценарии применения. Неправильный выбор приводит к лишним обращениям к базе и замедлению кода в циклах.

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

Что нужно знать о структуре регистра перед чтением

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

Для независимого непериодического регистра ключ — это комбинация значений всех измерений. Для периодического к ключу добавляется поле Период. Для регистра, подчинённого регистратору, записи читаются через набор записей с отбором по регистратору, а менеджер записи для такого регистра недоступен.

Уточнить структуру можно в конфигураторе: откройте ветку «Регистры сведений», найдите нужный объект и посмотрите закладки «Данные» (измерения, ресурсы, реквизиты) и свойства «Периодичность» и «Режим записи».

Получение одной записи через менеджер записи

Менеджер записи — самый прямой способ прочитать одну запись по полному ключу. Создайте объект, заполните все измерения, затем вызовите метод Прочитать(). После этого проверьте свойство Выбран(): оно показывает, найдена ли запись в базе.

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

МенеджерЗаписи.Номенклатура = НоменклатураСсылка;

МенеджерЗаписи.ВидЦены = ВидЦеныСсылка;

МенеджерЗаписи.Прочитать();

Если МенеджерЗаписи.Выбран() Тогда

ТекущаяЦена = МенеджерЗаписи.Цена;

Иначе

Сообщить("Запись с таким ключом не найдена");

КонецЕсли;

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

Менеджер записи удобен ещё и тем, что через него можно сразу изменить и сохранить запись: измените реквизиты и вызовите Записать(). Но для массовых операций в цикле этот способ медленный — каждая итерация делает отдельное обращение к базе.

bsl
МенеджерЗаписи = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период = ДатаКурса;
МенеджерЗаписи.Валюта = ВалютаСсылка;
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
    Курс = МенеджерЗаписи.Курс;
КонецЕсли;

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

Запрос — основной инструмент, когда нужно получить несколько записей, отобрать их по условию или соединить с другими таблицами. Запрос к физической таблице регистра выглядит как обращение к РегистрСведений.ИмяРегистра.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Цены.Номенклатура,

| Цены.Цена

|ИЗ

| РегистрСведений.ЦеныНоменклатуры КАК Цены

|ГДЕ

| Цены.Номенклатура = &Номенклатура";

Запрос.УстановитьПараметр("Номенклатура", НоменклатураСсылка);

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

Пока Выборка.Следующий() Цикл

Сообщить(Строка(Выборка.Цена));

КонецЦикла;

Передавайте значения через параметры (&Имя), а не конкатенацией строк — это защищает от ошибок с типами и от внедрения текста в запрос. Для проверки наличия хотя бы одной записи эффективнее использовать ВЫБРАТЬ ПЕРВЫЕ 1 и проверять Пустой() у результата, а не выгружать всю таблицу.

Если нужна выборка по списку значений (например, по массиву номенклатуры), передайте массив или список значений в параметр и используйте условие В (&Список). Это выполняется одним обращением к базе вместо цикла с менеджерами записей.

Срез последних и срез первых для периодических регистров

Частая задача: получить актуальное значение ресурса на дату — текущий курс валюты, действующую цену. Для этого у периодических регистров есть виртуальные таблицы СрезПоследних и СрезПервых.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Срез.Валюта,

| Срез.Курс

|ИЗ

| РегистрСведений.КурсыВалют.СрезПоследних(&Дата, Валюта = &Валюта) КАК Срез";

Запрос.УстановитьПараметр("Дата", ТекущаяДатаСеанса());

Запрос.УстановитьПараметр("Валюта", ВалютаСсылка);

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

Если Не Результат.Пустой() Тогда

Выборка = Результат.Выбрать();

Выборка.Следующий();

Курс = Выборка.Курс;

КонецЕсли;

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

СрезПервых работает зеркально: возвращает самые ранние записи начиная с указанной даты. Он нужен реже — например, чтобы найти дату первого установленного значения.

Сравнение способов чтения

Менеджер записи

Одна запись по полному ключу, нужно сразу изменить и записать. Не подходит для циклов и регистров, подчинённых регистратору.

Запрос к таблице

Выборки по условиям, соединения, массовое чтение одним обращением. Требует знания синтаксиса запросов.

СрезПоследних / СрезПервых

Актуальное или первое значение на дату в периодическом регистре. Для непериодических регистров недоступно.

Набор записей с отбором

Чтение движений регистра, подчинённого регистратору, или пакетная замена записей по ключу. Тяжелее запроса для простого чтения.

Чтение регистра, подчинённого регистратору

Если регистр записывается документом, отдельной «записи» в понимании менеджера записей у него нет — есть движения конкретного документа. Чтобы их получить, используйте набор записей с отбором по регистратору или запрос с условием Регистратор = &Документ.

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

НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);

НаборЗаписей.Прочитать();

Для Каждого Запись Из НаборЗаписей Цикл

Сообщить(Строка(Запись.Статус));

КонецЦикла;

Для простого чтения без намерения изменять данные предпочтительнее запрос — он не блокирует таблицу и не подгружает объектную модель набора записей. Набор записей оправдан, когда движения нужно перезаписать.

Проверка результата и типичные ошибки

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

Типичные ошибки
01
Не заполнено одно из измерений — читается запись с пустым ключом, итог: ложное 'запись не найдена' или чужие данные.
02
Чтение менеджером записи в цикле по сотням элементов — сотни обращений к базе вместо одного запроса.
03
Условие отбора вынесено из параметров виртуальной таблицы в секцию ГДЕ — срез строится по всей таблице, запрос тормозит.
04
Попытка использовать СоздатьМенеджерЗаписи для регистра, подчинённого регистратору — ошибка выполнения.
05
Игнорирование Выбран() после Прочитать() — дальше по коду используются пустые значения.

Ещё одна ловушка — права доступа. Если у пользователя нет права чтения на регистр, код завершится ошибкой или вернёт пустой результат в зависимости от контекста. При отладке «не читается запись» сначала проверьте под полными правами, есть ли данные в принципе.

Контрольные точки

Как проверить результат

Менеджер записи после Прочитать()
Норма

Выбран() = Истина, ресурсы заполнены

Тревожный признак

Выбран() = Ложь — записи с таким ключом нет

Результат запроса
Норма

Пустой() = Ложь, выборка обходится

Тревожный признак

Пустой() = Истина — проверить параметры и отбор

Срез последних
Норма

Возвращена строка с периодом <= даты среза

Тревожный признак

Пусто — нет записей раньше даты среза или отбор слишком узкий

Как выбрать способ под свою задачу

Маршрут решения

Как выбрать действие

Известен полный ключ записи и нужно прочитать или изменить одну записьИспользуйте СоздатьМенеджерЗаписи() с заполнением всех измерений
Нужно несколько записей или отбор по условиюПишите запрос к таблице РегистрСведений.ИмяРегистра
Нужно актуальное значение на дату в периодическом регистреИспользуйте виртуальную таблицу СрезПоследних с отбором в параметрах
Регистр подчинён регистраторуЧитайте запросом по Регистратор или набором записей с отбором
Чтение идёт в цикле по коллекцииВынесите чтение в один запрос с условием В (&Список) вместо обращений внутри цикла

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

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

Итог

Что важно запомнить

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

Частые вопросы

Как проверить, существует ли запись, не читая её целиком?

Используйте запрос с ВЫБРАТЬ ПЕРВЫЕ 1 и проверьте Результат.Пустой(). Это быстрее, чем выгружать все поля, и не требует объектной модели. Для менеджера записи достаточно Прочитать() и проверить Выбран().

Почему Прочитать() не находит запись, хотя она есть в базе?

Чаще всего не заполнено одно из измерений или значение отличается по типу — например, передана пустая ссылка или строка вместо ссылки. Сравните ключ в коде с фактической записью через консоль запросов или просмотр регистра в режиме предприятия.

Как получить последнюю запись периодического регистра без запроса?

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

Можно ли читать регистр сведений на клиенте?

В управляемом приложении прямое обращение к РегистрыСведений доступно только на сервере. В тонком и веб-клиенте вызывайте серверную процедуру, которая выполнит чтение и вернёт результат. Для кэшируемых данных используйте повторное использование возвращаемых значений.

Что быстрее: менеджер записи или запрос для одной записи?

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

Как получить записи регистра за период?

Запросом к таблице регистра с условием Период МЕЖДУ &Начало И &Конец. Для независимого периодического регистра это обычная выборка; виртуальные таблицы СрезПоследних/СрезПервых тут не нужны, так как требуется история, а не одно актуальное значение.