В процессе сопровождения и администрирования баз данных на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с необходимостью исправить ошибки учета задним числом. Традиционный путь — изменение документов и их последующее перепроведение — далеко не всегда применим. Перепроведение документов за прошлые закрытые периоды может привести к непредсказуемому изменению себестоимости, «сплыванию» партионного учета, нарушению последовательностей и искажению сданной отчетности.
В таких ситуациях возникает задача прямой замены ссылок на элементы справочников непосредственно в движениях регистров, минуя механизм проведения. В файловых версиях баз данных (формат DBF) ручная правка физических таблиц DBF с помощью сторонних редакторов превращается в трудоемкий процесс, особенно если некорректная ссылка присутствует в десятках или сотнях записей движений различных регистров. Нам потребуется автоматизировать этот процесс.
В этой статье мы подробно рассмотрим два основных подхода к решению этой задачи:
1С++ и прямых запросов.Также мы разберем критическую ошибку, из-за которой процесс конвертации базы данных из DBF в SQL может внезапно прерываться аварийным завершением работы Конфигуратора (ошибка доступа к памяти Memory Access Violation), и найдем способ её устранения.
---
Для того чтобы не связываться с долгой процедурой выгрузки и загрузки базы данных, мы можем прибегнуть к механизму прямых запросов к таблицам DBF. Стандартные средства 1С 7.7 не позволяют выполнять произвольные низкоуровневые SQL-запросы к собственной базе данных, однако внешняя компонента 1С++ (1cpp.dll) предоставляет такую возможность.
Сначала проанализируем структуру хранения данных в файловой версии 1С 7.7. Каждому регистру накопления или сведений в базе данных соответствуют физические файлы на диске:
RA328.dbf и индексный файл RA328.cdx). Именно в этих таблицах хранятся детальные записи движений, которые совершают документы при проведении.RG328.dbf). В них хранятся рассчитанные на начало каждого месяца остатки по измерениям.Для замены одной ссылки на другую во всех движениях определенного регистра нам необходимо выполнить операцию UPDATE для соответствующей таблицы RA*. Для этого воспользуемся возможностями OLE DB-провайдера FoxPro (Microsoft Visual FoxPro OLE DB Provider или VFPOLEDB), который отлично справляется с модификацией файлов формата DBF/CDX.
Рассмотрим пример кода на языке 1С 7.7 с использованием объектной модели 1С++ для прямого обновления данных в таблице движения регистра:
// Создаем объект для работы с базой данных через ADODB/OLEDB
БазаДанных = СоздатьОбъект("OLEDBData");
// Формируем строку подключения к текущей базе данных DBF
ПутьКБазе = КаталогИБ();
СтрокаПодключения = "Provider=VFPOLEDB.1;Data Source=" + ПутьКБазе + ";Mode=ReadWrite;Collating Sequence=MACHINE;";
Попытка
БазаДанных.Соединение(СтрокаПодключения);
Исключение
Предупреждение("Не удалось установить прямое соединение с таблицами DBF!");
Возврат;
КонецПопытки;
// Перед выполнением запросов модификации рекомендуется выполнить настройки FoxPro для стабильности
// Отключаем строгую валидацию таблиц для предотвращения конфликтов совместного доступа
БазаДанных.ВыполнитьИнструкцию("SET TABLEVALIDATE TO 0");
БазаДанных.ВыполнитьИнструкцию("SET ANSI OFF");
// Подготавливаем параметры замены
// В 1С 7.7 ссылки внутри таблиц DBF хранятся в виде уникального 13-символьного идентификатора (ID) объекта
ID_Старый = ЗначениеВСтрокуВнутр(СсылкаНаСтарыйЭлемент); // Преобразуем в строку внутреннего формата
ID_Новый = ЗначениеВСтрокуВнутр(СсылкаНаНовыйЭлемент);
// Извлекаем чистый идентификатор (обычно последние 6 или 9 символов в зависимости от типа метаданных)
// Для примера вырежем ID элемента справочника (длина 6 символов в кодировке 36-ричной системы)
ЧистыйID_Старый = Сред(ID_Старый, 5, 6);
ЧистыйID_Новый = Сред(ID_Новый, 5, 6);
// Определяем имя физического файла таблицы движений нужного регистра
// Выяснить точное имя таблицы (например, RA123) можно, заглянув в файл словаря данных 1cv7.dd
ИмяТаблицыДвижений = "RA123";
ИмяПоляСправочника = "SP124"; // Имя колонки измерения регистра, ссылающегося на справочник
// Составляем текст прямого SQL-запроса на обновление записи
ТекстЗапроса = "UPDATE " + ИмяТаблицыДвижений + " SET " + ИмяПоляСправочника + " = '" + ЧистыйID_Новый + "' WHERE " + ИмяПоляСправочника + " = '" + ЧистыйID_Старый + "'";
Попытка
БазаДанных.ВыполнитьИнструкцию(ТекстЗапроса);
Сообщить("Замена ссылок в движениях регистра успешно выполнена!");
Исключение
Сообщить("Ошибка при выполнении прямого UPDATE: " + ОписаниеОшибки(), "!");
КонецПопытки;
Важное предупреждение: При прямом обновлении таблиц движений RA* вы меняете только детальные записи. Накопленные итоги в таблицах RG* при этом не изменятся автоматически. В результате ваши отчеты (например, «Ведомость по остаткам») начнут показывать некорректные или «разорванные» данные: движения будут относиться к новому элементу справочника, а остатки по-прежнему будут числиться за старым.
Чтобы восстановить логическую целостность и актуализировать остатки, после завершения выполнения всех прямых SQL-запросов обязательно запустите процедуру полного пересчета итогов регистров. Для этого зайдите в режиме «Предприятие» в меню Операции -> Управление оперативным учетом -> Установить ТА на... (или выполните пересчет через режим «Монопольно» -> Администрирование -> Пересчет итогов).
В качестве более стабильной и современной альтернативы провайдеру VFPOLEDB для работы с DBF-файлами напрямую мы рекомендуем использовать компоненту 1sqlite. Она позволяет подключить базу данных 1С 7.7 в виртуальное окружение SQLite, предоставляя полноценный SQL-синтаксис и гарантируя отсутствие зависаний и конфликтов блокировок файлов индексов (*.cdx) при работе пользователей в базе данных.
---
Если объем исправлений велик (замена требуется в десятках различных таблиц регистров и документов), то писать индивидуальные SQL-запросы под каждую таблицу в DBF становится нерационально. В этом случае наиболее надежный и проверенный практикой путь — временный перенос базы данных на СУБД MS SQL Server, запуск универсальной SQL-обработки и последующий возврат базы обратно в файловый формат DBF.
Для SQL-версий 1С 7.7 существует мощный и проверенный годами инструментарий. В частности, на порталах сообщества программистов доступна обработка, выполняющая прямой поиск и замену ссылок во всех SQL-таблицах базы данных 1С без перепроведения документов. Она мгновенно находит и заменяет бинарные идентификаторы во всех таблицах шапок документов (DH*), табличных частей (DT*), движений регистров (RA*) и даже системной таблице подчиненности и связей (1SCRDOC).
Разберем стандартную последовательность действий для этого сценария:
1cv7.zip), содержащий файл конфигурации 1cv7.md и текстовый файл данных 1cv7.dat.BkEnd.dll).---
При выполнении вышеописанного сценария миграции на этапе загрузки данных в созданную SQL-базу многие специалисты сталкиваются с внезапным падением программы. Процесс загрузки запускается, создаются таблицы, загружается большинство документов, но на определенном виде документа Конфигуратор молча или с ошибкой операционной системы закрывается.
Проанализируем причины этой критической ошибки, которая часто ставит в тупик даже опытных системных администраторов и программистов 1С 7.7.
Выясним причину сбоя на примере документа под условным названием «СверткаИБ» (или любого аналогичного документа, создаваемого вспомогательными обработками свертки базы данных). Этот документ обладает уникальной спецификой:
RA* ссылаются на его IDDOC как на документ-регистратор).В файловой версии (DBF) платформа 1С 7.7 оптимизирует дисковое пространство. Если у документа нет реквизитов шапки и табличной части, то физические файлы таблиц DHxxxx.dbf и DTxxxx.dbf для него в каталоге базы данных просто не создаются. В DBF-формате система прекрасно работает и без них: сам документ существует как запись в общем журнале 1SJOURN, а его движения лежат в таблицах регистров.
Однако при конвертации в SQL-формат ситуация кардинально меняется:
1cv7.md и генерирует на лету файл словаря базы данных 1cv7.dds.1cv7.dds для него отсутствуют описания таблиц _1S_DHxxxx и _1S_DTxxxx.1cv7.dat. При обработке таблиц движений регистров СУБД наталкивается на ссылки на документ свертки. Платформа пытается сопоставить эти ссылки со словарем метаданных и физическими таблицами шапок документов на стороне SQL.1cv7s.exe.Пошаговая инструкция по исправлению ошибки загрузки:
Для того чтобы обойти это ограничение платформы и успешно загрузить базу данных в MS SQL Server, нам необходимо принудительно заставить конфигуратор создать физическую таблицу шапки документа в СУБД. Сделаем это следующим образом:
ФиктивныйРеквизит, тип данных — Строка, длина — 10 символов.1cv7.dd и физически создаст пустые таблицы DH* для этого документа.После успешной работы в SQL-версии и обратного переноса данных в DBF вы можете при желании удалить этот фиктивный реквизит из конфигурации, однако его наличие абсолютно безвредно и гарантирует, что при любых последующих технологических операциях выгрузки/загрузки вы больше не столкнетесь с досадным падением системы.
---
Если вы решите автоматизировать прямую замену ссылок (на стороне SQL или DBF с помощью 1С++), проанализируйте еще один важнейший элемент структуры базы данных 1С 7.7 — таблицу 1SCRDOC (таблица подчиненности документов и общих реквизитов с отбором).
В этой таблице хранятся связи между документами («документ-основание — подчиненный документ»), а также ссылки на элементы справочников, если эти справочники выбраны в качестве значений общих реквизитов документов с установленным флагом «Отбор по реквизиту».
При прямой замене ссылок в таблицах документов (например, в табличной части DT*) обязательно нужно корректировать записи и в таблице 1SCRDOC. В противном случае нарушится работа отборов в журналах документов и механизм структуры подчиненности. Но здесь кроется серьезный подводный камень:
Риск дублирования уникального индекса:
Представьте ситуацию, когда в табличной части одного и того же документа в разных строках были указаны два разных элемента справочника: «Товар №1» (заменяемый) и «Товар №2» (на который мы заменяем). При проведении такого документа в таблицу 1SCRDOC были записаны две строки связи данного документа с обоими товарами.
Если мы выполним простой запрос типа:
UPDATE _1SCRDOC SET MDID = 'Товар_Новый' WHERE MDID = 'Товар_Старый'
СУБД попытается изменить строку связи со старым товаром на новый товар. Но строка связи с новым товаром для этого документа уже существует в таблице! В результате СУБД попытается записать дублирующие данные в поля, входящие в состав уникального кластерного индекса таблицы 1SCRDOC. Это вызовет ошибку СУБД Duplicate Key Error, и транзакция будет отменена.
Для безопасной замены ссылок в системной таблице 1SCRDOC используйте более сложный алгоритм:
1SCRDOC для заменяемого значения, для которых еще нет аналогичных записей с новым значением для того же документа-владельца. Обновите их прямым запросом UPDATE.DELETE.Соблюдение этих правил, детальный анализ структуры метаданных и обязательный пересчет итогов после любых прямых манипуляций гарантируют быструю, безопасную и корректную работу вашей базы данных 1С:Предприятие 7.7.