При обслуживании и оптимизации баз данных на платформе 1С:Предприятие 7.7 нередко возникает задача наведения порядка в справочниках. За долгие годы работы в системе накапливаются тысячи позиций номенклатуры, которые были загружены ошибочно (например, из сторонних прайс-листов), созданы дублирующимися карточками или не имеют никаких движений по учету. Попытка автоматизировать поиск таких «мусорных» элементов через прямые SQL-запросы с использованием компоненты 1С++ часто приводит разработчиков к идее фильтрации по полю ROW_ID. Выясним, почему такой подход содержит скрытые риски и как правильно составить запрос для выявления неиспользуемой номенклатуры.
Рассмотрим логику, которую часто пытаются применить: получить максимальный идентификатор строки ROW_ID для номенклатуры, по которой были движения до определенной даты, а затем отобрать все позиции без движений, у которых значение ROW_ID меньше полученного числа. На первый взгляд кажется, что поле с автоинкрементом строго отражает хронологию добавления записей. Однако в архитектуре СУБД MS SQL под управлением 1С 7.7 это предположение ошибочно по следующим причинам:
IDENTITY сбрасывается и генерируется в новом порядке. В результате вся историческая хронология соответствия ROW_ID реальному моменту создания карточки полностью стирается.ROW_ID.ROW_ID увеличивается вхолостую, образуя разрывы.Таким образом, колонка ROW_ID является исключительно внутренним физическим счетчиком таблицы СУБД и никак не гарантирует дату и время создания элемента в прикладном смысле.
Проанализируем структуру первичного ключа справочников 1С 7.7. Внутренний идентификатор объекта хранится в поле ID (тип данных CHAR(9)):
0–9 и A–Z).Если база данных никогда не работала в режиме распределенной структуры, то 36-ричная последовательность ID формируется платформой последовательно. Однако и она не дает точной календарной даты, если не привязана к реальным событиям конфигурации.
Разберем способы, позволяющие выяснить, когда именно карточка появилась в системе:
_1SCONST). Если в конфигурации у справочника «Номенклатура» хотя бы один реквизит объявлен периодическим (например, базовая цена, ставка НДС, статус товара), то в момент первичной записи карточки платформа создает строку в таблице _1SCONST. Поле OBJID хранит идентификатор элемента, а поле DATE — дату фиксации значения. Выполнив группировку MIN(DATE) по идентификатору позиции, можно определить фактическую дату появления элемента в учете.Если задача заключается в очистке базы от позиций, которые ни разу не фигурировали в складских остатках и оборотах, фильтрацию по времени создания можно исключить вовсе либо ограничиться анализом самого регистра. Посмотрим на базовый запрос к таблице регистра «ОстаткиТМЦ» с помощью синтаксиса метаимен 1С++:
SELECT
Спр.ID as [Номенклатура $Справочник.Номенклатура]
FROM
$Справочник.Номенклатура AS Спр
WHERE
Спр.IsFolder = 2
AND Спр.IsMark = 0
AND Спр.ID NOT IN (
SELECT DISTINCT $Ост.Номенклатура
FROM $Регистр.ОстаткиТМЦ AS Ост
)
Разберем логику условий:
Спр.IsFolder = 2 — исключает из выборки группы справочника, отбирая только элементы.Спр.IsMark = 0 — отсекает элементы, которые уже помечены на удаление.NOT IN (или NOT EXISTS) проверяет факт полного отсутствия идентификатора номенклатуры среди измерений таблицы движений регистра.Проанализируем риски прямого удаления элементов из базы данных на уровне СУБД. Проверка только таблицы регистра накопления (например, ОстаткиТМЦ) является недостаточной:
Если принудительно удалить найденные позиции прямой SQL-командой DELETE, в табличных частях существующих документов останутся некорректные идентификаторы, что приведет к появлению строк с надписью «<Объект не найден>».
Безопасный порядок действий при очистке:
НайтиСсылки(). Метод проверит всю информационную базу (документы, константы, периодику, проводки) и зафиксирует, есть ли реальные ссылки на элемент.Удалить(1) или перенести в специальную архивную группу справочника, исключив их из видимости пользователей при оперативном подборе.