В процессе обновления конфигурации базы данных на сервере MS SQL Server можно столкнуться с критической ошибкой реструктуризации:
Ошибка СУБД: Microsoft SQL Server Native Client 11.0: Cannot insert the value NULL into column '_Fld426', table 'trd_zubr_bd.dbo._Reference27NG'; column does not allow nulls. INSERT fails. HRESULT=80040E2F, SQLSrvr: SQLSTATE=23000, state=2, Severity=10, native=515, line=1.
Разберем по шагам, почему возникает эта ошибка, как быстро выяснить проблемный объект метаданных и какие существуют надежные способы восстановления работоспособности информационной базы.
Рассмотрим подробнее внутренний механизм обновления 1С на уровне СУБД. Когда платформа выполняет реструктуризацию таблицы метаданных (например, при изменении типов данных реквизитов, установке признаков запрета пустых значений или обновлении структуры справочника), происходят следующие операции:
_Reference27NG), содержащая обновленную структуру с ограничениями NOT NULL.INSERT INTO ... SELECT ....Если в исходной таблице SQL физически содержатся недопустимые значения NULL (что может случиться из-за прямых SQL-запросов, некорректно завершенных транзакций, сбоев динамического обновления или изменения состава типов реквизитов), операция переноса завершается аварийно, так как новое поле СУБД не допускает пустых значений NULL.
Выясним причину сбоя, сопоставив имена таблиц и полей SQL с реальными объектами конфигурации 1С. Для этого воспользуемся встроенной функцией ПолучитьСтруктуруХраненияБазыДанных().
Запустим внешнюю обработку в режиме предприятия или выполним следующий фрагмент программного кода:
СтруктураБазы = ПолучитьСтруктуруХраненияБазыДанных();
Для Каждого СтрокаТаблицы Из СтруктураБазы Цикл
Если СтрокаТаблицы.ИмяТаблицыХранения = "_Reference27" Тогда
Сообщить("Объект метаданных: " + СтрокаТаблицы.Метаданные);
Для Каждого Поле Из СтрокаТаблицы.Поля Цикл
Если Поле.ИмяПоляХранения = "_Fld426" Тогда
Сообщить("Имя реквизита: " + Поле.Метаданные);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
В результате мы получим точное наименование справочника (например, Справочник.БанковскиеСчета) и проблемного реквизита (например, НомерСчета).
Проанализируем данные найденного объекта через запрос в режиме 1С:Предприятие:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Ссылка,
| НомерСчета
|ИЗ
| Справочник.БанковскиеСчета КАК БанковскиеСчета
|ГДЕ
| БанковскиеСчета.НомерСчета ЕСТЬ NULL
| ИЛИ БанковскиеСчета.НомерСчета = """"";
Результат = Запрос.Выполнить().Выгрузить();
ПоказатьОповещениеПользователя("Найдено пустых элементов: " + Формат(Результат.Количество(), "ЧГ=0"));
Для исправления достаточно программно или интерактивно заполнить проблемные поля корректными значениями по умолчанию либо пометить на удаление и удалить испорченные или пустые элементы (например, созданные в ходе предыдущего некорректного тестирования и исправления базы).
Если база данных не открывается в режиме предприятия, исправление можно выполнить прямым SQL-запросом к исходной таблице (без суффикса NG). В зависимости от типа данных поля выполним соответствующую команду:
UPDATE _Reference27 SET _Fld426 = '' WHERE _Fld426 IS NULL;
UPDATE _Reference27 SET _Fld426 = 0 WHERE _Fld426 IS NULL;
UPDATE _Reference27 SET _Fld426 = '2001-01-01 00:00:00' WHERE _Fld426 IS NULL;
UPDATE _Reference27 SET _Fld426 = 0x00000000000000000000000000000000 WHERE _Fld426 IS NULL;
Если точечное исправление на сервере SQL вызывает затруднения, применим надежный метод через локальную файловую информационную базу:
.dt через Конфигуратор..dt.NULL значениями по умолчанию..dt и восстановим ее на рабочем SQL-сервере.Важное примечание: При аварийном прерывании обновления на сервере SQL может остаться недосозданная таблица с суффиксом NG. Перед повторным запуском обновления обязательно проверьте и при необходимости удалите «зависшую» временную таблицу в Management Studio, чтобы избежать ошибок дублирования имен объектов.