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

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

Ссылочный тип данных в 1С: простое объяснение и практика

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

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

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

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

Какие объекты в 1С имеют ссылочный тип

Не все сущности конфигурации являются ссылочными. Ссылочный тип имеют те объекты, которые существуют в базе как самостоятельные записи с уникальным идентификатором: справочники, документы, перечисления, планы видов характеристик, планы счетов, планы видов расчёта, бизнес-процессы, задачи, планы обмена. Каждый такой объект хранится в своей таблице базы данных, а ссылка — это фактически его первичный ключ.

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

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

Чем ссылка отличается от объекта

Ключевое различие, которое нужно понять с самого начала: ссылка и объект — это разные сущности. Ссылка — лёгкое значение, идентификатор. Объект — это «загруженная в память» копия данных с возможностью изменения и записи. Для справочника «Номенклатура» это типы СправочникСсылка.Номенклатура и СправочникОбъект.Номенклатура соответственно.

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

ТоварСсылка = Справочники.Номенклатура.НайтиПоКоду("000001");

ТоварОбъект = ТоварСсылка.ПолучитьОбъект();

ТоварОбъект.Наименование = "Новое наименование";

ТоварОбъект.Записать();

Важно помнить о производительности: каждое обращение к реквизиту ссылки через точку вне транзакции запроса — это отдельное обращение к базе данных. В цикле по тысяче строк такой код выполняет тысячу лишних чтений. Правильный подход — получить все нужные данные одним запросом и работать с выборкой.

Пустая ссылка и её проверка

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

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

Если Не ЗначениеЗаполнено(СтрокаТаблицы.Контрагент) Тогда

Сообщить("Не указан контрагент");

КонецЕсли;

// Альтернатива для конкретного типа:

Если Контрагент = Справочники.Контрагенты.ПустаяСсылка() Тогда

// действие

КонецЕсли;

В запросах пустая ссылка проверяется через параметр: ГДЕ Контрагент = &ПустойКонтрагент, где параметру присваивается Справочники.Контрагенты.ПустаяСсылка(). Отдельный случай — «битая ссылка», когда реквизит указывает на удалённый объект. Проверка ЗначениеЗаполнено для неё вернёт Истина, но обращение к реквизитам даст ошибку или значение вида «Объект не найден». Надёжная проверка в запросе — соединение с таблицей справочника и проверка результата на NULL.

Сравнение и типизация ссылок

Ссылки сравниваются оператором равенства: две ссылки равны, если указывают на один и тот же объект одного и того же типа. Сравнивать ссылку со строкой или с GUID в текстовом виде нельзя — результат будет ложным или приведёт к ошибке. Если из внешней системы пришёл идентификатор в виде строки, его нужно преобразовать в ссылку через Новый УникальныйИдентификатор и метод ПолучитьСсылку.

Определить тип значения помогает функция ТипЗнч() и сравнение с Тип("СправочникСсылка.Номенклатура"). Это стандартный приём в универсальных процедурах, принимающих параметры произвольного типа:

Если ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура") Тогда

// обработка товара

ИначеЕсли ТипЗнч(Значение) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда

// обработка документа

КонецЕсли;

Составные типы — реквизиты, которые могут хранить ссылки разных видов (например, «Контрагент» как справочник или «Основание» как один из нескольких документов) — проверяются тем же способом. В запросах для составных типов используется конструкция ВЫРАЗИТЬ(... КАК ...) или функция ТИПЗНАЧЕНИЯ() для отбора по конкретному виду ссылки.

Как безопасно найти и изменить элемент справочника
  1. 1
    Найдите ссылку методом НайтиПоКоду, НайтиПоНаименованию или запросом
  2. 2
    Проверьте результат через ЗначениеЗаполнено — поиск может вернуть пустую ссылку
  3. 3
    Вызовите ПолучитьОбъект() только если нужно изменять данные
  4. 4
    Измените реквизиты объекта и вызовите Записать()
  5. 5
    При массовой обработке оберните запись в транзакцию и обработайте исключения

Ссылочные типы в запросах

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

Рекомендуемая практика — явные соединения вместо разыменования там, где нужно несколько полей одного объекта, и осторожность с конструкцией «через точку» в условиях ГДЕ: она мешает оптимизатору использовать индексы. Также в запросах доступны функции ТИПЗНАЧЕНИЯ(Поле), предопределённое значение ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) и проверка ЕСТЬ NULL.

Типичные ошибки при работе со ссылками
01
Сравнение ссылки со строкой наименования — результат всегда ложный, объект не находится
02
Изменение реквизитов через ссылку без ПолучитьОбъект() — ошибка выполнения
03
Обращение к реквизитам ссылки в цикле — сотни лишних запросов к базе
04
Проверка только ЗначениеЗаполнено при наличии битых ссылок — ошибка «Объект не найден» при обращении
05
Смешение типов в составном реквизите без проверки ТипЗнч — логические ошибки в обработках

Практические приёмы и ограничения

Несколько приёмов, которые регулярно встречаются в реальной разработке. Получить ссылку по известному GUID: Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаGUID)). Получить GUID существующей ссылки: Ссылка.УникальныйИдентификатор(). Это стандартный способ обмена идентификаторами между базами и внешними системами.

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

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

Как проверить корректность работы со ссылками

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

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

Итог

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

Ссылочный тип — это указатель на объект базы, а не сам объект. Читать данные можно через ссылку, изменять — только через ПолучитьОбъект(). Пустоту проверяйте функцией ЗначениеЗаполнено, тип — через ТипЗнч, а в запросах избегайте разыменования в условиях и циклах с обращениями к реквизитам ссылки.

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

Чем ссылочный тип отличается от примитивного?

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

Как узнать, какого типа ссылка хранится в реквизите?

Используйте функцию ТипЗнч(Значение) и сравните результат с нужным типом через Тип("СправочникСсылка.ИмяСправочника"). В запросах аналог — функция ТИПЗНАЧЕНИЯ(Поле) или конструкция ССЫЛКА в условиях.

Что такое битая ссылка и как её найти?

Битая ссылка — значение, указывающее на удалённый объект. В интерфейсе она отображается как «Объект не найден». В запросе её можно выявить левым соединением с таблицей справочника и проверкой поля на NULL — если соединение не нашло запись, ссылка битая.

Можно ли изменить данные объекта через ссылку?

Нет. Через ссылку доступно только чтение реквизитов. Для изменения нужно вызвать метод ПолучитьОбъект(), изменить свойства полученного объекта и выполнить Записать(). Попытка присвоения реквизиту ссылки завершится ошибкой.

Как получить ссылку по GUID из внешней системы?

Создайте значение идентификатора конструктором Новый УникальныйИдентификатор(СтрокаGUID), затем вызовите метод менеджера ПолучитьСсылку(Идентификатор). Если объект с таким GUID отсутствует в базе, метод вернёт ссылку, обращение к данным которой покажет, что объекта не существует.

Почему запрос с обращением через точку работает медленно?

Каждое разыменование вида Таблица.Ссылка.Реквизит в запросе порождает неявное соединение с таблицей соответствующего справочника или документа. При множестве таких обращений и в условиях ГДЕ оптимизатор не может эффективно использовать индексы. Заменяйте разыменование явными соединениями и убирайте его из условий отбора.