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

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

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

«Не удалось вставить значение NULL в столбец "_LineNo", таблицы "..._AccXX_ExtDimYYYNG"; в столбце запрещены значения NULL. Ошибка в INSERT.»

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

Почему возникает эта ошибка при реструктуризации

Проанализируем механику работы платформы 1С:Предприятие при реструктуризации таблиц:

  1. Таблицы с суффиксом NG (New Generation) создаются платформой временно в процессе реструктуризации для переноса данных в измененную структуру.
  2. Имя таблицы формата _AccXX_ExtDimYYY указывает на подчиненную табличную часть видов субконто определенного плана счетов (например, Хозрасчетный). Столбец _LineNo хранит номер строки этой табличной части и имеет строгое ограничение СУБД NOT NULL.
  3. В процессе обновления платформа выполняет внутренний запрос переноса данных через конструкцию INSERT INTO ... SELECT ..., соединяя данные счетов и связанного плана видов характеристик (например, ВидыСубконтоХозрасчетные).
  4. Если в плане видов характеристик произошло задвоение предопределенных элементов (два или более элемента ссылаются на одно и то же системное имя), операция соединения таблиц возвращает неоднозначный результат или декартово произведение, в котором для системного поля _LineNo формируется значение NULL. Это и вызывает падение процесса на уровне SQL-сервера.

Такие дубли обычно появляются в результате некорректных обменов через РИБ (когда при ОбменДанными.Загрузка = Истина контроль уникальности платформы отключается), после обновления конфигураций с ручными доработками или при переносе данных между версиями платформ.

Шаг 1. Поиск задвоенных предопределенных элементов

Разберем по шагам, как выявить задвоенные виды субконто. Для этого выполним поиск дубликатов по свойству ИмяПредопределенныхДанных в режиме «1С:Предприятие».

Создадим внешнюю обработку или откроем консоль запросов и выполним следующий запрос:


ВЫБРАТЬ
    ВидыСубконто.ИмяПредопределенныхДанных КАК Имя,
    КОЛИЧЕСТВО(ВидыСубконто.Ссылка) КАК Количество
ИЗ
    ПланВидовХарактеристик.ВидыСубконтоХозрасчетные КАК ВидыСубконто
ГДЕ
    ВидыСубконто.ИмяПредопределенныхДанных <> ""
СГРУППИРОВАТЬ ПО
    ВидыСубконто.ИмяПредопределенныхДанных
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(ВидыСубконто.Ссылка) > 1

Если доступ к пользовательскому режиму заблокирован или требуется проверка непосредственно на стороне SQL-сервера, определим имя физической таблицы через функцию ПолучитьСтруктуруХраненияБазыДанных() и выполним запрос в Management Studio:


SELECT _PredefinedID, COUNT(*) 
FROM dbo._ChrXXXX 
WHERE _PredefinedID <> 0x00000000000000000000000000000000
GROUP BY _PredefinedID 
HAVING COUNT(*) > 1;

Шаг 2. Устранение дубликатов предопределенных элементов

Рассмотрим, как правильно избавиться от дубля. Стандартными средствами пометить предопределенный элемент на удаление нельзя. Нам необходимо программно снять признак предопределенности с дублирующей записи.

Разберем программный алгоритм исправления:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВидыСубконто.Ссылка КАК Ссылка
    |ИЗ
    |   ПланВидовХарактеристик.ВидыСубконтоХозрасчетные КАК ВидыСубконто
    |ГДЕ
    |   ВидыСубконто.ИмяПредопределенныхДанных = &ИмяДубля";

Запрос.УстановитьПараметр("ИмяДубля", "Контрагенты"); // Указываем найденное имя дубля
Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Количество() > 1 Тогда
    // Пропускаем первый (оригинальный) элемент, обрабатываем дубли
    Выборка.Следующий();
    
    Пока Выборка.Следующий() Цикл
        ОбъектСубконто = Выборка.Ссылка.ПолучитьОбъект();
        ОбъектСубконто.ИмяПредопределенныхДанных = "";
        ОбъектСубконто.Записать();
    КонецЦикла;
КонецЕсли;

После очистки реквизита ИмяПредопределенныхДанных дублирующий элемент превращается в обычный пользовательский элемент. Теперь с помощью стандартной обработки «Поиск и удаление дублей» перенаправим все ссылки с дубля на исходный предопределенный элемент и удалим ставший ненужным объект.

Шаг 3. Временное отключение обновления предопределенных данных

Если реструктуризация прерывается при попытке открыть базу или запустить обновление, применим обходной маневр, временно отключив механизм синхронизации предопределенных данных:

  1. Откроем свойства конфигурации в дереве метаданных.
  2. Найдем свойство «Обновление предопределенных данных» и переведем его в значение Не обновлять автоматически. Также для конкретного объекта метаданных можно использовать метод УстановитьОбновлениеПредопределенныхДанных().
  3. Выполним обновление конфигурации базы данных (клавиша F7) — в таком режиме реструктуризация пройдет успешно без проверки соответствия предопределенных записей.
  4. Запустим систему в режиме «1С:Предприятие», выполним Шаг 1 и Шаг 2 для полной очистки дубликатов.
  5. Вернем свойство «Обновление предопределенных данных» в значение Автообновление и еще раз применим изменения в конфигураторе.

Таким образом, устранение задвоенных записей в плане видов характеристик восстанавливает целостность связей данных и позволяет успешно завершить обновление плана счетов.

← На главную