Как очистить битые ссылки в базе данных 1С средствами SQL

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В процессе эксплуатации информационных систем на базе 1С неизбежно возникают ситуации, когда в базе данных появляются так называемые «битые» ссылки. Это записи в таблицах (например, в регистрах сведений), которые ссылаются на объекты (документы или справочники), уже удаленные из системы. На больших объемах данных штатные средства «Тестирования и исправления» могут работать слишком долго, поэтому опытные разработчики прибегают к прямой очистке через SQL. В этой статье мы разберем, как реализовать этот процесс, не покидая среду 1С, и на что следует обратить внимание.

Организация подключения к MSSQL из 1С

Для того чтобы выполнить запрос к базе данных SQL напрямую из программного кода 1С, чаще всего используются технологии ADO (ActiveX Data Objects) или COM-соединение. Это позволяет передавать команды серверу баз данных в реальном времени. Рассмотрим, как проинициализировать такое соединение. Мы будем использовать объект ADODB.Connection.

Проанализируем типичный алгоритм создания подключения:


// Создаем объект соединения
Connection = Новый COMОбъект("ADODB.Connection");

// Формируем строку подключения (ConnectionString)
// Здесь указываем сервер, имя базы, логин и пароль
ConnectionString = "Provider=SQLOLEDB.1;Data Source=" + ИмяСервера + ";Initial Catalog=" + ИмяБазы + ";User ID=" + Логин + ";Password=" + Пароль + ";";

Попытка
    Connection.Open(ConnectionString);
Исключение
    Сообщить("Ошибка подключения: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

Если ваша база работает на платформе 1С:Предприятие 8.3, рассмотрите также использование механизма Внешних источников данных. Это более современный и безопасный способ интеграции, который позволяет работать с SQL-таблицами почти так же, как с обычными объектами метаданных 1С, сохраняя типизацию данных.

Поиск соответствия имен таблиц 1С и SQL

Главная сложность при работе с SQL напрямую заключается в том, что имена таблиц в СУБД (например, _InfoRg1234) не совпадают с именами в конфигураторе (например, РегистрСведений.ЦеныНоменклатуры). Чтобы сопоставить их, нам понадобится встроенная функция платформы ПолучитьСтруктуруХраненияБазыДанных().

Разберем по шагам, как получить имя таблицы регистра:

  1. Вызываем функцию ПолучитьСтруктуруХраненияБазыДанных() для конкретного объекта метаданных.
  2. Проходим циклом по результату и находим имя таблицы в колонке ИмяТаблицыХранения.

Пример кода для получения имени таблицы:


МассивИмен = Новый Массив;
МассивИмен.Добавить("РегистрСведений.ИмяВашегоРегистра");
СтруктураТаблиц = ПолучитьСтруктуруХраненияБазыДанных(МассивИмен);

Для Каждого СтрокаТаблицы Из СтруктураТаблиц Цикл
    Если СтрокаТаблицы.Метаданные = "РегистрСведений.ИмяВашегоРегистра" Тогда
        ИмяТаблицыSQL = СтрокаТаблицы.ИмяТаблицыХранения;
        Прервать;
    КонецЕсли;
КонецЦикла;

Работа с составными типами данных в SQL

Ситуация усложняется, если поле, которое мы хотим проверить на «битость», имеет составной тип данных (например, «ДокументСсылка»). В SQL-таблицах 1С такие поля представляются несколькими колонками. Выясним причину такого строения: платформе нужно хранить не только уникальный идентификатор (GUID), но и информацию о том, к какой именно таблице этот идентификатор относится.

Обычно используются следующие колонки:

Чтобы определить, является ли ссылка битой в составном поле, нужно сначала сопоставить значение из колонки _TYPE с конкретной таблицей документа, а затем проверить наличие записи с соответствующим _RRef в этой таблице. Для простых (несоставных) ссылок достаточно проверить наличие _RRef в целевой таблице объекта.

Алгоритм очистки «битых» записей через SQL

Самый эффективный способ поиска — использование конструкции LEFT JOIN. Мы выбираем все записи из регистра и пытаемся «присоединить» к ним таблицу-объект (справочник или документ). Если в присоединенной таблице значение оказывается NULL, значит, ссылка битая.

Рассмотрим пример SQL-запроса для удаления записей из регистра сведений, где ссылка на документ-регистратор потеряна:


DELETE FromReg
FROM _InfoRg100 AS FromReg
LEFT JOIN _Document200 AS TargetDoc 
    ON FromReg._Fld300_RRef = TargetDoc._IDRRef
WHERE TargetDoc._IDRRef IS NULL 
  AND FromReg._Fld300_TYPE = 0x08 -- Идентификатор типа для документов

В этом примере:

Критические риски и меры предосторожности

Работа напрямую с SQL — это мощный, но опасный инструмент. Проанализируем основные риски:

1. Объектный кэш сервера 1С. Сервер приложений 1С «не видит» изменений, внесенных напрямую в SQL. В памяти сервера могут остаться старые данные, которые вы уже удалили. Рекомендация: после массовой очистки через SQL обязательно перезапустите службу сервера 1С или выполните очистку серверного кэша.

2. Целостность данных. В 1С данные часто связаны сложнее, чем кажется. Ссылки могут дублироваться в индексах, итогах регистров накопления или последовательностях. Простое удаление строки из одной таблицы может нарушить логику итогов. Для простых независимых регистров сведений этот метод безопасен, но для регистров накопления или бухгалтерии — крайне рискован.

3. Индексы и статистика. После масштабного удаления записей (более 10-20% объема таблицы) обязательно выполните Rebuild Indexes и обновите статистику SQL-сервера. Это предотвратит деградацию производительности при последующей работе с этими таблицами.

Вывод: Очистка через SQL оправдана на сверхбольших базах (терабайтного уровня), где стандартное ТиИ не справляется по времени. В остальных случаях лучше использовать штатные механизмы 1С или готовые обработки с проверенных ресурсов, которые учитывают логику платформы.

← На главную