Как устранить ошибку «Не удалось вставить значение NULL в столбец _LineNo» при обновлении базы 1С?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет Промышленность, строительство и АПК
← На главную

При обновлении конфигурации или применении изменений в структуре базы данных на сервере MS SQL Server разработчики и администраторы могут столкнуться с критической ошибкой реструктуризации: «Microsoft SQL Server Native Client: Не удалось вставить значение NULL в столбец "_LineNo", таблицы "...dbo._Acc..._ExtDim...NG"; в столбце запрещены значения NULL». Разберем детально, почему возникает этот сбой, почему ручные правки на уровне СУБД оказываются бесполезными и как правильно восстановить целостность данных штатными средствами 1С.

Почему попытка изменить свойства таблицы в SQL Server Management Studio не помогает

Первое побуждение при получении ошибки СУБД — открыть SQL Server Management Studio (SSMS), найти указанную таблицу и разрешить в проблемной колонке значения NULL. Однако при повторном запуске обновления из конфигуратора ошибка воспроизводится вновь.

Проанализируем архитектуру процесса обновления. Имя таблицы с суффиксом NG (New Generation) указывает на то, что платформа выполняет классическую реструктуризацию данных. Механизм работает следующим образом:

  1. Платформа 1С создает во временном пространстве СУБД абсолютно новую пустую таблицу с суффиксом NG на основе обновленного описания метаданных.
  2. В эту новую таблицу копируются данные из рабочей таблицы пакетной операцией вида INSERT INTO ...NG SELECT ... FROM ....
  3. После успешного переноса старая таблица удаляется, а таблица с суффиксом NG переименовывается в рабочую.

Когда мы меняем флаг разрешения NULL в исходной таблице, это никак не влияет на создаваемую «на лету» таблицу ...NG, так как ее структура генерируется ядром платформы заново с жестким ограничением NOT NULL на уровне первичного ключа. Следовательно, исправлять нужно не схему СУБД, а исходные данные, которые приводят к генерации неопределенного значения.

Суть проблемы: связь плана счетов и таблицы субконто

Выясним назначение таблицы, вызвавшей сбой. Таблицы формата _Acc[ID]_ExtDim[ID] отвечают за хранение строк табличной части видов субконто плана счетов. Поле _LineNo содержит порядковый номер субконто (1, 2, 3 и т.д.) для конкретного счета и вместе со ссылкой на счет (_Account_IDRRef) входит в состав первичного ключа.

В момент переноса данных платформа сопоставляет счета, пересчитывает их аналитику и внутреннюю иерархию. Если у какого-либо счета нарушена ссылочная целостность, сбита маска кода или не заполнен служебный реквизит Порядок, внутренний алгоритм платформы не может корректно сопоставить запись и передает в поле _LineNo значение NULL, что немедленно прерывает транзакцию реструктуризации.

Диагностика проблемных счетов через SQL

Перед тем как приступать к исправлению, локализуем сбойные записи в СУБД. Рассмотрим несколько проверочных запросов к основной таблице плана счетов и таблице его субконто.

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С:Предприятие до выполнения реструктуризации и принудительно рассчитаем порядок для всех счетов с помощью встроенного метода менеджера плана счетов ПолучитьПорядокКода():


Выборка = ПланыСчетов.Хозрасчетный.Выбрать();
Пока Выборка.Следующий() Цикл
    СчетОбъект = Выборка.ПолучитьОбъект();
    // Рассчитываем правильный порядок на основании кода счета
    СчетОбъект.Порядок = ПланыСчетов.Хозрасчетный.ПолучитьПорядокКода(СчетОбъект.Код);
    Попытка
        СчетОбъект.Записать();
    Исключение
        Сообщить("Не удалось записать счет: " + СчетОбъект.Код + " - " + ОписаниеОшибки());
    КонецПопытки;
КонецЦикла;

После успешного выполнения алгоритма откроем конфигуратор и повторим обновление базы данных. Реструктуризация завершится штатно.

Альтернативные причины и методы обхода

Если заполнение реквизита Порядок не помогло, рассмотрим дополнительные факторы, способные вызывать сбой:

  1. Задвоение предопределенных видов субконто. Если в плане видов характеристик (например, «Виды субконто хозрасчетные») появились дубли предопределенных элементов с одинаковыми именами, воспользуемся штатной обработкой ПоискИУдалениеДублей и объединим задвоенные позиции.
  2. Временный перенос в файловую базу. Выгрузка информационной базы в файл .dt, загрузка в файловый вариант, выполнение обновления конфигурации и последующая обратная загрузка на SQL Server. Движок файловой базы менее жестко проверяет ограничения целостности СУБД и пропускает реструктуризацию. Однако этот способ лишь маскирует проблему: поврежденные данные останутся в базе и могут проявиться ошибками при расчете итогов или формировании оборотно-сальдовой ведомости.
  3. Оптимизированная реструктуризация. Начиная с платформы 8.3.11 доступен ускоренный режим реструктуризации. Если запустить обновление конфигурации базы данных через командную строку с параметром /UpdateDbCfg -Dynamic- -Server, платформа стремится применить инструкции ALTER TABLE напрямую в СУБД без полного копирования данных в промежуточную таблицу с суффиксом NG.
← На главную