При выполнении прямых SQL-запросов к базе данных 1С:Предприятие 7.7 разработчики часто сталкиваются с ситуацией, когда простая инструкция UPDATE не находит нужные строки или некорректно очищает реквизиты ссылочного типа. Выясним причину такого поведения и разберем по шагам, как устроено хранение ссылок на документы в SQL-таблицах платформы 1С 7.7, а также рассмотрим рабочие способы решения этой задачи.
Разберем механику хранения ссылочных данных в SQL-базе 1С 7.7. Формат поля в таблице базы данных (например, в таблицах шапки документов DH*) напрямую зависит от того, задан ли конкретный вид документа у реквизита или установлен неопределенный тип:
Документ.РасходнаяБН), в базе SQL он хранится в виде строки длиною 9 символов (CHAR(9)), содержащей уникальный идентификатор документа IDDOC.CHAR(13)). В этих 13 символах зашифрована составная ссылка: первые 4 символа содержат код вида документа в 36-ричной системе счисления (Base36), а следующие 9 символов — непосредственно IDDOC.Когда мы пытаемся выполнить сравнение реквизита неопределенного типа с обычным 9-символьным значением IDDOC или присвоить ему макрос $ПустойИД (который возвращает 9 символов), СУБД сравнит строки разной длины и запрос либо не вернет строк для обновления, либо запишет битые данные.
Чтобы корректно отфильтровать и очистить реквизит неопределенного типа «Документ» через прямой SQL-запрос с использованием внешней компоненты 1С++, необходимо сформировать 13-символьное значение ссылки, состоящее из кода вида документа в Base36 и его IDDOC.
Рассмотрим рабочий пример SQL-запроса, в котором очищается реквизит ДокументПолнойОплаты в документе РасходнаяБН:
Текст = "
|UPDATE Накладная
|SET
| $Накладная.ДокументПолнойОплаты = $ПустойИД
|FROM $Документ.РасходнаяБН AS Накладная
|INNER JOIN _1sjourn AS журнал ON журнал.iddoc = :Документ
|WHERE $Накладная.ДокументПолнойОплаты = $ВидДокумента36." + ПДНС.Вид() + " + журнал.iddoc";
Проанализируем ключевые моменты этого запроса:
$ВидДокумента36.ИмяВида автоматически подставляет 4-символьный префикс вида документа в кодировке Base36.$ВидДокумента36.Вид + журнал.iddoc дает полные 13 символов, с которыми корректно сравнивается реквизит неопределенного типа.$ПустойИД13 или строка из 13 пробелов.Проводя прямые изменения в SQL-таблицах платформы 1С 7.7, необходимо учитывать архитектурные ограничения:
_1scrdoc): прямой UPDATE таблицы шапки документа (DH*) не изменяет системную таблицу связей _1scrdoc. Если очищаемый реквизит участвует в структуре подчиненности, документ продолжит отображаться в дереве подчиненных документов до выполнения операции «Пересчет служебных данных» в процессе «Тестирование и исправление информационной базы».Если задача заключается в том, чтобы изменить реквизиты шапки без повторного формирования движений по регистрам и без риска нарушить целостность _1scrdoc, рекомендуется использовать штатные средства языка 1С 7.7.
Метод Записать() обновляет реквизиты документа и структуру подчиненности, сбрасывает кэш и не вызывает процедуру ОбработкаПроведения():
Док = СоздатьОбъект("Документ.РасходнаяБН");
Если Док.НайтиДокумент(НужныйДокумент) = 1 Тогда
Док.ДокументПолнойОплаты = ПолучитьПустоеЗначение("Документ");
Док.Записать(); // Обновляет реквизиты шапки и таблицу связей, не меняя движения
КонецЕсли;
Этот подход гарантирует полное соответствие логике 1С:Предприятие 7.7 и исключает необходимость проведения тестирования и исправления базы данных.