При обслуживании и тестировании баз данных на платформе 1С:Предприятие разработчики и администраторы иногда сталкиваются со специфическими ошибками логической целостности. Одна из самых коварных проблем — появление «осиротевших» строк в табличных частях. Физически запись существует в таблице базы данных, но ее поле связи с родителем (владельцем) содержит пустой уникальный идентификатор (GUID). При попытке выполнить стандартное Тестирование и исправление (ТИИ) система аварийно завершает работу с сообщением: «Ошибка SDBL: Тип поля FLD... несовместим с типом литерала UNDEFINED».
В этой статье мы подробно разберем, почему возникает эта ошибка, почему стандартные инструменты платформы оказываются бессильными, и рассмотрим три проверенных практических метода полного устранения этой проблемы как для клиент-серверных, так и для файловых баз данных.
Давайте проанализируем внутреннее устройство СУБД 1С. Любая табличная часть справочника или документа в физической таблице базы данных хранится отдельно от основной таблицы объекта. Связь между ними осуществляется с помощью специального служебного поля ссылки (обычно это поле называется по шаблону _ReferenceXX_IDRRef для справочников или _DocumentXX_IDRRef для документов).
Если в результате аппаратного сбоя, некорректного динамического обновления или программной ошибки в таблицу ТЧ записывается строка, у которой поле связи заполнено двоичными нулями (00000000-0000-0000-0000-000000000000), возникает логическое противоречие. Запись в подчиненной таблице есть, а объекта-владельца с таким идентификатором не существует.
Рассмотрим, почему штатные механизмы диагностики не могут исправить эту ситуацию:
chdbfl.exe предназначена исключительно для проверки физической целостности файла базы данных 1Cv8.1cd (структура страниц, целостность заголовков таблиц, индексы). Она не проверяет логические связи между таблицами и не знает, что запись ТЧ должна обязательно ссылаться на существующий элемент справочника.Неопределено (UNDEFINED). Из-за строгого соответствия типов СУБД отвергает это сравнение, и ТИИ «вылетает» с ошибкой несовместимости типов, так и не успев удалить дефектную строку.Справочники.Организации.ПустаяСсылка().ПолучитьОбъект() всегда возвращает Неопределено, следовательно, мы не можем очистить или перезаписать табличную часть пустой ссылки штатными методами встроенного языка.Ниже мы подробно разберем три рабочих сценария решения этой проблемы.
Если ваша информационная база работает в клиент-серверном режиме (под управлением MS SQL Server, PostgreSQL, IBM DB2 или Oracle), исправить проблему проще всего. Нам достаточно выполнить прямой запрос на удаление проблемной строки из соответствующей физической таблицы.
Рассмотрим этот процесс по шагам:
Шаг 1. Определение физического имени таблицы и полей. Сначала нам необходимо выяснить, в какой именно таблице СУБД хранятся данные нашей табличной части. Для этого мы можем запустить обработку «Получить структуру хранения базы данных» или выполнить простой программный код во внешней обработке:
СтруктураБазы = ПолучитьСтруктуруХраненияБазыДанных("Справочник.Организации", Истина);
Для Каждого Таблица Из СтруктураБазы Цикл
Если Таблица.ИмяМетаданных = "Справочник.Организации.ТабличнаяЧасть.КонтактнаяИнформация" Тогда
Сообщить("Имя таблицы в СУБД: " + Таблица.ИмяТаблицыХранения);
Для Каждого Поле Из Таблица.Поля Цикл
Если Поле.ИмяМетаданных = "Ссылка" Тогда
Сообщить("Имя поля связи: " + Поле.ИмяПоляХранения);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Предположим, что в результате мы выяснили: физическая таблица называется _Reference31_VT3892, а поле связи (идентификатор владельца) — _Reference31_IDRRef.
Шаг 2. Выполнение SQL-запроса на удаление. Теперь нам нужно открыть консоль управления СУБД (например, SQL Server Management Studio или pgAdmin) и выполнить запрос на удаление записи, у которой поле связи состоит из одних нулей.
Для базы данных под управлением MS SQL Server запрос будет выглядеть следующим образом:
DELETE FROM _Reference31_VT3892
WHERE _Reference31_IDRRef = 0x00000000000000000000000000000000;
Для базы данных под управлением PostgreSQL синтаксис двоичного литерала будет немного отличаться:
DELETE FROM _Reference31_VT3892
WHERE _Reference31_IDRRef = '\x00000000000000000000000000000000';
После выполнения этого запроса дефектная строка физически удалится из базы данных. Вы можете сразу запустить Тестирование и исправление в 1С — оно пройдет без каких-либо ошибок.
Что делать, если база данных файловая, разворачивать SQL-сервер нет возможности, а использовать сторонние низкоуровневые утилиты не хочется? Мы можем прибегнуть к стандартному методу выгрузки/загрузки данных с временным удалением метаданных.
Проанализируем по шагам этот алгоритм:
Организации. Поскольку выгрузка работает через объектную модель 1С, она будет обходить только существующие элементы справочника. Наша «осиротевшая» строка из табличной части не имеет родителя, поэтому она гарантированно не попадет в файл выгрузки XML.Организации, перейдем на вкладку «Табличные части», выберем поврежденную табличную часть (например, КонтактнаяИнформация) и удалим её.1Cv8.1cd таблицу, предназначенную для хранения этой табличной части, вместе со всеми записями (включая дефектную пустую строку).Еще один эффективный метод для файловых баз — прямое редактирование таблиц базы данных с помощью сторонней утилиты Tool1CD (или ее аналогов для работы с форматом 1CD). Этот инструмент позволяет просматривать и редактировать таблицы файловой базы напрямую, минуя уровень платформы 1С.
Выполним следующие действия:
1Cv8.1cd в отдельный каталог для создания резервной копии. Ни в коем случае не выполняйте операции редактирования на работающей базе!Tool1CD и откроем в ней файл базы данных._REFERENCE31_VT3892).После сохранения изменений запустим базу данных в режиме Конфигуратора и выполним Тестирование и исправление (только проверку логической целостности). Система успешно пройдет проверку, подтверждая исправление структуры данных.
Мы подробно рассмотрели технические нюансы возникновения ошибки SDBL, связанной с «осиротевшими» записями табличных частей, и разобрали три метода борьбы с этой неполадкой. На практике наиболее быстрым и безопасным решением является перевод базы на SQL и удаление записи простым запросом DELETE. Для небольших файловых баз отлично подойдет метод с временным удалением табличной части через XML-выгрузку, так как он гарантирует полную сохранность структуры базы данных силами самой платформы.