В процессе обновления конфигурации или применения изменений в структуре базы данных разработчики и администраторы нередко сталкиваются с аварийным завершением реструктуризации. Платформа выдает системное сообщение вида: «Ошибка СУБД: Ошибка SQL: Запись значения NULL в поле, не допускающее NULL '_FLD556'». Разберем по шагам, почему возникает эта ошибка, как найти поврежденную таблицу и какими методами восстановить работоспособность информационной базы.
Выясним причину такого поведения платформы. При обновлении конфигурации или изменении состава реквизитов платформа 1С запускает механизм реструктуризации таблиц. Внутренний механизм переносит данные из старой структуры во временную таблицу, а затем формирует новую структуру с ограничением NOT NULL для всех колонок.
Сбой происходит в следующих случаях:
NULL, которого там быть не должно.NULL, что вызывает отказ СУБД._LineNo) либо ссылками на удаленные элементы.Проанализируем имя поля из ошибки, например _FLD556. Это внутренний идентификатор колонки в СУБД. Чтобы понять, какому объекту конфигурации и реквизиту оно принадлежит, воспользуемся штатной функцией глобального контекста ПолучитьСтруктуруХраненияБазыДанных().
Запустим базу в режиме «1С:Предприятие» (до применения обновления) и выполним в обработке или консоли следующий код:
СтруктураБазы = ПолучитьСтруктуруХраненияБазыДанных();
ИскомоеПоле = "_FLD556";
Для Каждого СтрТаблица Из СтруктураБазы Цикл
Для Каждого СтрПоле Из СтрТаблица.Поля Цикл
Если ВРег(СтрПоле.ИмяПоляХранения) = ВРег(ИскомоеПоле) Тогда
Сообщить("Найдено совпадение!");
Сообщить("Метаданные: " + СтрТаблица.Имя);
Сообщить("Имя таблицы хранения: " + СтрТаблица.ИмяТаблицыХранения);
Сообщить("Реквизит: " + СтрПоле.Имя);
Сообщить("Тип реквизита: " + СтрПоле.ТипЗначения);
КонецЕсли;
КонецЦикла;
КонецЦикла;
После выполнения кода мы точно узнаем, в каком объекте (например, справочник РасчетныеСчета или табличная часть документа) находится сбойный реквизит.
Рассмотрим самый быстрый и простой способ, не требующий сторонних утилит. Если ошибка вызвана внутренним сбоем индексов или несоответствием структуры, вызовем принудительную реструктуризацию таблицы объекта штатными средствами конфигуратора:
РасчетныеСчета).РеквизитВременный с типом Булево).NULL.Если в таблице присутствуют записи с нарушенной ссылочной целостностью, выполним их программную перезапись. При вызове метода Записать() платформа автоматически приводит все незаполненные поля к типам по умолчанию вместо NULL.
Посмотрим на пример обработки для справочника:
Выборка = Справочники.РасчетныеСчета.Выбрать();
Пока Выборка.Следующий() Цикл
Попытка
Объект = Выборка.ПолучитьОбъект();
Если Объект <> Неопределено Тогда
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
КонецЕсли;
Исключение
Сообщить("Ошибка при записи элемента: " + Выборка.Ссылка + " | " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Флаг ОбменДанными.Загрузка = Истина позволяет обойти прикладные проверки при записи, гарантируя сохранение элемента и корректное заполнение полей на уровне СУБД.
Штатная процедура «Тестирование и исправление» (ТИИ) не всегда помогает по умолчанию, если не заданы параметры обработки ссылочных ошибок. Выполним следующие действия:
Если база работает в файловом режиме (.1CD), и встроенные средства платформы не справляются с исправлением битых строк, применим обход через СУБД:
.dt в пустую клиент-серверную базу на MS SQL Server или PostgreSQL.NULL:
UPDATE _Reference123
SET _FLD556 = 0x00000000000000000000000000000000
WHERE _FLD556 IS NULL;
_Reference123 и _FLD556 — имена таблицы и поля из структуры хранения)..dt и загрузим в файловый режим.Применение одного из описанных методов позволяет устранить несоответствие типов и успешно завершить процедуру обновления информационной базы.