В процессе эксплуатации информационных систем на базе 1С неизбежно возникают ситуации, когда в базе данных появляются так называемые «битые» ссылки. Это записи в таблицах (например, в регистрах сведений), которые ссылаются на объекты (документы или справочники), уже удаленные из системы. На больших объемах данных штатные средства «Тестирования и исправления» могут работать слишком долго, поэтому опытные разработчики прибегают к прямой очистке через SQL. В этой статье мы разберем, как реализовать этот процесс, не покидая среду 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С, сохраняя типизацию данных.
Главная сложность при работе с SQL напрямую заключается в том, что имена таблиц в СУБД (например, _InfoRg1234) не совпадают с именами в конфигураторе (например, РегистрСведений.ЦеныНоменклатуры). Чтобы сопоставить их, нам понадобится встроенная функция платформы ПолучитьСтруктуруХраненияБазыДанных().
Разберем по шагам, как получить имя таблицы регистра:
ПолучитьСтруктуруХраненияБазыДанных() для конкретного объекта метаданных.ИмяТаблицыХранения.Пример кода для получения имени таблицы:
МассивИмен = Новый Массив;
МассивИмен.Добавить("РегистрСведений.ИмяВашегоРегистра");
СтруктураТаблиц = ПолучитьСтруктуруХраненияБазыДанных(МассивИмен);
Для Каждого СтрокаТаблицы Из СтруктураТаблиц Цикл
Если СтрокаТаблицы.Метаданные = "РегистрСведений.ИмяВашегоРегистра" Тогда
ИмяТаблицыSQL = СтрокаТаблицы.ИмяТаблицыХранения;
Прервать;
КонецЕсли;
КонецЦикла;
Ситуация усложняется, если поле, которое мы хотим проверить на «битость», имеет составной тип данных (например, «ДокументСсылка»). В SQL-таблицах 1С такие поля представляются несколькими колонками. Выясним причину такого строения: платформе нужно хранить не только уникальный идентификатор (GUID), но и информацию о том, к какой именно таблице этот идентификатор относится.
Обычно используются следующие колонки:
Binary(1)).Binary(16)).Чтобы определить, является ли ссылка битой в составном поле, нужно сначала сопоставить значение из колонки _TYPE с конкретной таблицей документа, а затем проверить наличие записи с соответствующим _RRef в этой таблице. Для простых (несоставных) ссылок достаточно проверить наличие _RRef в целевой таблице объекта.
Самый эффективный способ поиска — использование конструкции 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 -- Идентификатор типа для документов
В этом примере:
_InfoRg100 — таблица вашего регистра._Document200 — таблица документов, на которые ссылается регистр._Fld300_RRef — колонка со ссылкой в регистре._IDRRef — уникальный идентификатор в таблице документа.Работа напрямую с SQL — это мощный, но опасный инструмент. Проанализируем основные риски:
1. Объектный кэш сервера 1С. Сервер приложений 1С «не видит» изменений, внесенных напрямую в SQL. В памяти сервера могут остаться старые данные, которые вы уже удалили. Рекомендация: после массовой очистки через SQL обязательно перезапустите службу сервера 1С или выполните очистку серверного кэша.
2. Целостность данных. В 1С данные часто связаны сложнее, чем кажется. Ссылки могут дублироваться в индексах, итогах регистров накопления или последовательностях. Простое удаление строки из одной таблицы может нарушить логику итогов. Для простых независимых регистров сведений этот метод безопасен, но для регистров накопления или бухгалтерии — крайне рискован.
3. Индексы и статистика. После масштабного удаления записей (более 10-20% объема таблицы) обязательно выполните Rebuild Indexes и обновите статистику SQL-сервера. Это предотвратит деградацию производительности при последующей работе с этими таблицами.
Вывод: Очистка через SQL оправдана на сверхбольших базах (терабайтного уровня), где стандартное ТиИ не справляется по времени. В остальных случаях лучше использовать штатные механизмы 1С или готовые обработки с проверенных ресурсов, которые учитывают логику платформы.