Каталог решений - T-SQL + 1С: нумерация записей табличных частей и наборов регистров по порядку

T-SQL + 1С: нумерация записей табличных частей и наборов регистров по порядку

T-SQL + 1С: нумерация записей табличных частей и наборов регистров по порядку

В наличии

Обработка данных больших баз 1С часто выполняется средствами SQL. Это может быть свёртка или какая-то другая задача. После выполнения команды DELETE может нарушиться последовательность нумерации записей табличной части или набора регистра. Это может привести к неприятным последствиям, если её не восстановить. В данной публикации приводится достаточно простое решение этой проблемы.

Категория:

Описание

Предположим, что нам необходимо свернуть все движения по выбывшей из оборота номенклатуре. Мы выполнили удаление движений по регистрам накопления и обнаружили, что нумерация записей наборов нарушилась. Это может выглядеть примерно вот так (значения в ячейках имеют демонстрационный характер для упрощения восприятия):

_Period_RecorderTRef_RecorderRRef_LineNo_Fld123RRef
01.01.2010 12:00:000x120x0110x11
01.01.2010 12:00:000x120x0120x22
01.01.2010 12:00:000x120x0140x44

 где

_Period — период регистра накопления;

_RecorderTRef — код типа документа, например, Документ.ПоступлениеТоваровУслуг;

_RecorderRRef — ссылка на документ (имеет тип binary(16), по факту является GUID’ом);

_LineNo — порядковый номер записи набора регистра;

_Fld123RRef — измерение, ссылка на элемент справочника «Номенклатура» (в нашем примере так).

В данной таблице не хватает записи с номером строки _LineNo равным 3. Эта строка была удалена в процессе свёртки. Если мы оставим это так как есть, то, например, при выполнении такого кода 1С (проверялось на платформе 8.3):

Набор = РегистрыНакопления.ТоварыНаСкладах.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(ДокументСсылка);
Набор.Прочитать();
Набор.Записать();

 Можно неожиданно получить вот такой результат:

_Period_RecorderTRef_RecorderRRef_LineNo_Fld123RRef
01.01.2010 12:00:000x120x0110x11
01.01.2010 12:00:000x120x0120x22
01.01.2010 12:00:000x120x0130x44
01.01.2010 12:00:000x120x0140x44

Последняя строка в наборе регистра задублировалась. Как это произошло? Моя гипотеза такова: набор записей был успешно прочитан в оперативную память, а затем, при его записи обратно в базу данных, 1С восстановила последовательность нумерации и та строка, которая имела значение поля _LineNo равным 4 стала равна 3. В таком виде набор записывается в базу данных, но строка со значением _LineNo равным 4 из базы данных не была удалена и к ней дописываются строки со значениями _LineNo равными 1, 2 и 3, которые они получили в оперативной памяти. Таким образом получается дублирование.

В таких случаях требуется восстановить последовательность нумерации строк. Как это сделать наиболее простым способом? Это можно сделать при помощи следующей команды SQL:

UPDATE T
SET
    T.[_LineNo] = T.[RowNumber] — Обновляем значения
FROM
    (SELECT
        T.[_LineNo] AS [_LineNo],
        — Нумерация по порядку средствами SQL — используем оконные функции
        ROW_NUMBER() OVER(PARTITION BY T.[_RecorderRRef] ORDER BY T.[_LineNo]) AS [RowNumber]
    FROM
        [ИмяТаблицыРегистра] AS T
        INNER JOIN
            (SELECT
                [_RecorderRRef]  AS [_RecorderRRef],
                COUNT([_LineNo]) AS [LineCount], — Количество строк в разрезе регистратора
                MAX([_LineNo])   AS [LineMax]    — Максимальное значение номера строки в разрезе регистратора
            FROM
                [ИмяТаблицыРегистра]
            WHERE
                [_Period] < @Period — Здесь может быть любое нужное нам условие отбора записей набора регистра
            GROUP BY
                [_RecorderRRef]
            HAVING
                COUNT([_LineNo]) <> MAX([_LineNo]) — Таким образом мы отбираем регистраторы, у которых нарушилась нумерация

has been added to your cart:
Оформление заказа