При обновлении конфигурации или применении изменений в структуре базы данных на сервере MS SQL Server разработчики и администраторы могут столкнуться с критической ошибкой реструктуризации: «Microsoft SQL Server Native Client: Не удалось вставить значение NULL в столбец "_LineNo", таблицы "...dbo._Acc..._ExtDim...NG"; в столбце запрещены значения NULL». Разберем детально, почему возникает этот сбой, почему ручные правки на уровне СУБД оказываются бесполезными и как правильно восстановить целостность данных штатными средствами 1С.
Первое побуждение при получении ошибки СУБД — открыть SQL Server Management Studio (SSMS), найти указанную таблицу и разрешить в проблемной колонке значения NULL. Однако при повторном запуске обновления из конфигуратора ошибка воспроизводится вновь.
Проанализируем архитектуру процесса обновления. Имя таблицы с суффиксом NG (New Generation) указывает на то, что платформа выполняет классическую реструктуризацию данных. Механизм работает следующим образом:
NG на основе обновленного описания метаданных.INSERT INTO ...NG SELECT ... FROM ....NG переименовывается в рабочую.Когда мы меняем флаг разрешения NULL в исходной таблице, это никак не влияет на создаваемую «на лету» таблицу ...NG, так как ее структура генерируется ядром платформы заново с жестким ограничением NOT NULL на уровне первичного ключа. Следовательно, исправлять нужно не схему СУБД, а исходные данные, которые приводят к генерации неопределенного значения.
Выясним назначение таблицы, вызвавшей сбой. Таблицы формата _Acc[ID]_ExtDim[ID] отвечают за хранение строк табличной части видов субконто плана счетов. Поле _LineNo содержит порядковый номер субконто (1, 2, 3 и т.д.) для конкретного счета и вместе со ссылкой на счет (_Account_IDRRef) входит в состав первичного ключа.
В момент переноса данных платформа сопоставляет счета, пересчитывает их аналитику и внутреннюю иерархию. Если у какого-либо счета нарушена ссылочная целостность, сбита маска кода или не заполнен служебный реквизит Порядок, внутренний алгоритм платформы не может корректно сопоставить запись и передает в поле _LineNo значение NULL, что немедленно прерывает транзакцию реструктуризации.
Перед тем как приступать к исправлению, локализуем сбойные записи в СУБД. Рассмотрим несколько проверочных запросов к основной таблице плана счетов и таблице его субконто.
1. Проверим наличие счетов с пустым или неинициализированным реквизитом порядка (замените _Acc28 на имя вашей таблицы плана счетов):
SELECT _IDRRef, _Code, _Description, _Order
FROM dbo._Acc28
WHERE _Order IS NULL OR _Order = '';
2. Проверим таблицу видов субконто на наличие «осиротевших» записей, которые ссылаются на несуществующие счета:
SELECT *
FROM dbo._Acc28_ExtDim775
WHERE _Account_IDRRef NOT IN (SELECT _IDRRef FROM dbo._Acc28);
3. Проанализируем наличие дубликатов субконто в рамках одного счета:
SELECT _Account_IDRRef, _DimKind_IDRRef, COUNT(*)
FROM dbo._Acc28_ExtDim775
GROUP BY _Account_IDRRef, _DimKind_IDRRef
HAVING COUNT(*) > 1;
Если запросы возвращают строки с пустым полем _Order или битыми связями, мы нашли источник ошибки.
В типовых и отраслевых конфигурациях стандартный реквизит Порядок формируется автоматически, но при переносе данных, объединении нетиповых конфигураций или прямых манипуляциях со счетами он может остаться незаполненным. В пользовательском интерфейсе этот реквизит зачастую недоступен для прямого редактирования.
Для исправления ситуации запустим внешнюю обработку в режиме 1С:Предприятие до выполнения реструктуризации и принудительно рассчитаем порядок для всех счетов с помощью встроенного метода менеджера плана счетов ПолучитьПорядокКода():
Выборка = ПланыСчетов.Хозрасчетный.Выбрать();
Пока Выборка.Следующий() Цикл
СчетОбъект = Выборка.ПолучитьОбъект();
// Рассчитываем правильный порядок на основании кода счета
СчетОбъект.Порядок = ПланыСчетов.Хозрасчетный.ПолучитьПорядокКода(СчетОбъект.Код);
Попытка
СчетОбъект.Записать();
Исключение
Сообщить("Не удалось записать счет: " + СчетОбъект.Код + " - " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
После успешного выполнения алгоритма откроем конфигуратор и повторим обновление базы данных. Реструктуризация завершится штатно.
Если заполнение реквизита Порядок не помогло, рассмотрим дополнительные факторы, способные вызывать сбой:
ПоискИУдалениеДублей и объединим задвоенные позиции..dt, загрузка в файловый вариант, выполнение обновления конфигурации и последующая обратная загрузка на SQL Server. Движок файловой базы менее жестко проверяет ограничения целостности СУБД и пропускает реструктуризацию. Однако этот способ лишь маскирует проблему: поврежденные данные останутся в базе и могут проявиться ошибками при расчете итогов или формировании оборотно-сальдовой ведомости./UpdateDbCfg -Dynamic- -Server, платформа стремится применить инструкции ALTER TABLE напрямую в СУБД без полного копирования данных в промежуточную таблицу с суффиксом NG.