При изучении внутреннего устройства платформы 1С:Предприятие у разработчиков часто возникают вопросы о том, как именно абстракции платформы транслируются в физические структуры реляционных СУБД (Microsoft SQL Server, PostgreSQL и др.). Рассмотрим подробно, как в базе данных представлены пустые значения различных типов, чем пустая ссылка отличается от значения Неопределено и NULL, а также почему 1С самостоятельно управляет ссылочной целостностью.
Для колонок с жестко заданным одиночным типом платформа 1С на уровне СУБД создает поля с модификатором NOT NULL и значениями по умолчанию. Проанализируем, что именно записывается в базу данных при сохранении незаполненных реквизитов:
СправочникСсылка.Контрагенты) и значение не выбрано, в поле фиксированной длины binary(16) (или bytea в PostgreSQL) записывается 16 нулевых байтов: 0x00000000000000000000000000000000. На уровне платформы это соответствует результату функции Справочники.Контрагенты.ПустаяСсылка().NULL, а как пустая строка фиксированной или переменной длины ''.0).0 (или false).0001-01-01 00:00:00 (либо 2001-01-01 00:00:00 при использовании смещения 2000 для совместимости с ранними версиями СУБД).Ситуация меняется, когда реквизит имеет составной тип (например, ЛюбаяСсылка или комбинацию из нескольких примитивных и ссылочных типов). В этом случае платформа не может обойтись одной физической колонкой и формирует группу связанных полей:
_TYPE — байтовый дискриминатор типа, определяющий, какой именно тип фактически сохранен в строке (число, строка, ссылка, дата, булево или признак отсутствия типа)._RTRef — идентификатор таблицы метаданных (4 байта), указывающий конкретную таблицу, на которую ссылается строка._RRRef — физический 16-байтный идентификатор ссылки (GUID)._N для чисел, _S для строк, _D для дат, _B для логических значений).Рассмотрим, как физически различаются состояния составного поля в таблице SQL:
_TYPE содержит маркер ссылки, _RTRef хранит код таблицы (например, справочника «Контрагенты»), а _RRRef заполнен нулями (0x00...00)._TYPE записывается маркер отсутствия типа (нулевой байт), а сопутствующие поля ссылки и значений либо обнуляются, либо принимают значение SQL NULL. Записать значение Неопределено в реквизит с жестко заданным одиночным типом средствами платформы невозможно.NULL появляется в неактивных полях составного типа для текущей строки, а также в реквизитах справочников, для которых установлено использование «Только для элемента» или «Только для группы» (в строках противоположного типа такие поля физически содержат NULL). Также NULL образуется при выполнении левых соединений в запросах.Разберем частый вопрос: является ли база 1С реляционной, если в схеме таблиц на стороне СУБД отсутствуют внешние ключи (FOREIGN KEY) и каскадные ограничения (ON DELETE CASCADE)?
База данных под управлением 1С остается реляционной, так как данные хранятся в отношениях (таблицах) и связываются по ключам. Однако поддержание ссылочной целостности и правил согласованности данных платформа полностью берет на себя на уровне собственного сервера приложений по следующим причинам:
НайтиПоСсылкам, удаление помеченных объектов) и объектные события (ПередЗаписью, ПередУдалением), что исключает необходимость каскадных удалений на уровне СУБД.Выясним, что происходит, если объект удаляется непосредственно (например, программным вызовом метода Удалить() без контроля ссылок):
_RRRef продолжает хранить прежний 16-байтный GUID, так как на стороне СУБД нет ограничений целостности.<Объект не найден> (GUID). Сама структура базы данных при этом остается целостной на физическом уровне.