Как получить подчиненные документы прямым SQL запросом в 1С 7.7

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При работе с высоконагруженными базами данных на платформе 1С 7.7 стандартные средства получения подчиненных документов, такие как объект ВыбратьПодчиненныеДокументы, могут работать медленно, особенно если дерево связей очень разветвленное. В таких случаях программисты прибегают к использованию прямых SQL-запросов (обычно через библиотеку 1CPP). Однако новички часто совершают ошибку, пытаясь найти связи в таблице журнала документов или через конкретные реквизиты шапки. Разберем, как это сделать правильно и эффективно.

Почему ваш запрос не находит подчиненные документы

Проанализируем типичную ошибку: попытку связать документы через реквизиты, хранящиеся в таблице журнала _1SJOURN или физических таблицах документов (например, $Документ.Договор). В 1С 7.7 связь "Основание — Подчиненный" не всегда хранится в явном виде в колонках таблиц документов. Даже если вы создали реквизит "ДокументОснование", стандартное системное дерево подчиненности строится по иному принципу.

Для корректного решения задачи нам необходимо обратиться к системной таблице _1SCRDOC. Именно в ней платформа регистрирует абсолютно все связи между объектами, которые отображаются в интерфейсе при нажатии кнопки "Дерево подчиненных документов".

Структура таблицы _1SCRDOC

Прежде чем писать запрос, рассмотрим структуру этой таблицы, так как она является ключом к решению:

  1. MDID — идентификатор метаданных. Если значение равно 0, это означает системную связь (общую подчиненность). Если значение больше 0, это связь по конкретному реквизиту.
  2. PARENTVAL — ссылка на родительский (основной) документ. Она хранится в специфическом бинарном или строковом формате (в зависимости от настроек SQL), который включает вид документа и его внутренний ID.
  3. CHILDID — 9-символьный идентификатор (IDDOC) подчиненного документа.
  4. CHILD_DATE_TIME_IDDOC — комбинированное поле, содержащее дату, время и ID подчиненного документа. Оно используется платформой для быстрой сортировки по хронологии.

Шаг 1: Правильное использование фильтра ParentVal

Выясним причину, по которой простые сравнения часто не срабатывают. Поле ParentVal в SQL-базе имеет длину 23 символа. Чтобы не формировать эту строку вручную (что чревато ошибками с типами данных), в библиотеке 1CPP предусмотрен специальный типизатор. Рассмотрим пример передачи параметра:

ODBCRecordSet.УстановитьТекстовыйПараметр("Родитель", ДокументСсылка);

В самом SQL-тексте мы будем использовать конструкцию :Родитель* (со звездочкой), что заставит компоненту развернуть ссылку в полный формат, понятный таблице _1SCRDOC.

Шаг 2: Написание SQL-запроса для получения подчиненных

Рассмотрим правильный пример запроса, который выберет все помеченные и не помеченные на удаление подчиненные документы для конкретного родителя. Мы объединим таблицу связей с журналом документов, чтобы получить вид документа и его номер.


SELECT
    Журнал.IDDOC [Документ $Документ],
    Журнал.IDDOCDEF Документ_вид,
    Журнал.DOCNO as НомерДокумента,
    CAST(LEFT(Журнал.DATE_TIME_IDDOC, 8) as DateTime) as ДатаДокумента
FROM
    _1SCRDOC as Ссылки WITH (NOLOCK)
INNER JOIN
    _1SJOURN as Журнал WITH (NOLOCK) ON Ссылки.CHILDID = Журнал.IDDOC
WHERE
    Ссылки.PARENTVAL = :Родитель*
    AND Ссылки.MDID = 0
    AND Журнал.ISMARK = 0
ORDER BY
    Журнал.DATE_TIME_IDDOC

Важные моменты в этом коде:

Шаг 3: Обработка пустых значений и типов

Проанализируем ситуацию, когда нам нужно проверить документ на пустое значение. В 1С 7.7 ссылки в SQL хранятся как строки. Сравнение с пустой строкой '' — это ошибка, так как идентификатор документа в SQL всегда имеет фиксированную длину (9 символов). Профессиональнее использовать макрос $ПустойИД.

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

| WHERE $ДокументДоговор.Контрагент <> $ПустойИД

Пошаговая отладка сложного запроса

Если ваш сложный запрос (как в примере из Сообщения 0) по-прежнему не возвращает данные, разберем методику пошаговой проверки:

  1. Изоляция: Сначала напишите простейший запрос только к _1SCRDOC для одного конкретного IDDOC, в подчиненности которого вы уверены.
  2. Проверка ParentVal: Убедитесь, что параметр :Родитель* передается корректно. Посмотрите в профайлере SQL (SQL Profiler), во что превращается этот параметр. Он должен выглядеть как строка вида 'O1' + IDDOCDEF_BASE36 + IDDOC.
  3. Хронология: Помните, что подчиненные документы могут быть созданы "задним числом". Если вы используете фильтры по датам в основном запросе (как ДатаНачала <= :ДатаДокум), убедитесь, что подчиненные документы попадают в этот интервал.

Заключение

Использование прямой таблицы связей _1SCRDOC — это единственный надежный и быстрый способ получения дерева подчиненности в 1С 7.7 через SQL. Попытки связать таблицы через sp... поля (как делал автор темы в sp1351) могут работать только для частных случаев, когда в конфигураторе явно указан тип реквизита "Документ.НужныйВид", но они бесполезны для общих связей. Используйте предложенный шаблон с INNER JOIN к журналу, и ваши отчеты будут работать мгновенно.

← На главную