Работа напрямую с базой данных SQL в обход сервера приложений 1С — это мощный инструмент, который требует глубокого понимания структуры хранения данных. В конфигурации 1С:УПП (Управление производственным предприятием) сотни документов, и задача найти вхождение конкретной номенклатуры во всех табличных частях за определенный период может показаться сложной. Разберем по шагам, как правильно составить такой запрос, на что обратить внимание и каких ошибок избежать.
Первое, с чем мы столкнемся, — это специфические имена таблиц и полей. Платформа 1С не хранит данные в таблицах с человекочитаемыми именами вроде Document.Sales. Вместо этого используются внутренние идентификаторы. Проанализируем основные префиксы:
Чтобы выяснить, какая именно таблица в SQL соответствует документу «Реализация товаров и услуг» или «Поступление товаров и услуг», нам необходимо воспользоваться встроенной функцией 1С ПолучитьСтруктуруХраненияБазыДанных(). Рассмотрим пример того, как получить эти данные через консоль запросов в самой 1С, прежде чем переходить в SQL Management Studio.
Номенклатура в 1С — это ссылочный тип данных. В SQL такие ссылки хранятся в формате binary(16). Это важнейший момент: поиск по строковому представлению GUID (например, "550e8400-e29b-41d4-a716-446655440000") не даст результата. Выясним, как найти нужный бинарный код. Сначала выполним запрос к справочнику номенклатуры, чтобы получить её _IDRRef:
SELECT _IDRRef
FROM _Reference25 -- Предположим, 25 - это ID справочника Номенклатура
WHERE _Description = 'Кирпич красный'
Полученное значение (например, 0x80C200155D05070111E27B6E94956C2D) мы будем использовать в качестве фильтра в условиях WHERE для наших табличных частей. Помните, что порядок байт в SQL инвертирован относительно того, что мы видим в коде 1С, поэтому надежнее всего брать _IDRRef прямо из таблицы справочника в той же базе.
Проанализируем ситуацию с периодом. 1С хранит даты в SQL со смещением, которое чаще всего составляет 2000 лет. Это делается для корректной обработки пустых дат. Если нам нужно отфильтровать документы за январь 2024 года, в SQL-запросе мы должны прибавить 2000 лет к искомым датам.
Например, условие для выбора данных за январь 2024 года будет выглядеть так:
WHERE _Date_Time >= '4024-01-01' AND _Date_Time < '4024-02-01'
Поскольку номенклатура может встречаться в разных документах (Реализация, Поступление, Требование-накладная и т.д.), нам придется объединять результаты из разных таблиц. Разберем пример структуры запроса для двух видов документов:
SELECT 'Реализация' AS DocType, T1._Date_Time, T2._Fld1234 -- Количество
FROM _Document100 T1 -- Шапка реализации
INNER JOIN _Document100_VT105 T2 ON T1._IDRRef = T2._Document100_IDRRef -- ТЧ товары
WHERE T2._Fld1056_RRRef = 0x80C200155D05070111E27B6E94956C2D -- Наша номенклатура
AND T1._Date_Time BETWEEN '4024-01-01' AND '4024-01-31'
UNION ALL
SELECT 'Поступление', T1._Date_Time, T2._Fld2345
FROM _Document110 T1 -- Шапка поступления
INNER JOIN _Document110_VT115 T2 ON T1._IDRRef = T2._Document110_IDRRef
WHERE T2._Fld1158_RRRef = 0x80C200155D05070111E27B6E94956C2D
AND T1._Date_Time BETWEEN '4024-01-01' AND '4024-01-31'
Обратите внимание на использование _Posted. Если нам нужны только проведенные документы, обязательно добавим AND T1._Posted = 0x01. В противном случае запрос выберет и помеченные на удаление, и просто записанные документы.
Писать UNION ALL для 50+ таблиц вручную — задача неблагодарная. Профессионалы используют динамический SQL. Мы можем написать скрипт, который просканирует системную таблицу sys.columns, найдет все таблицы с префиксом _VT, в которых есть колонки, ссылающиеся на номенклатуру, и автоматически сформирует текст запроса.
Рассмотрим логику поиска таких таблиц:
_Document%_VT%._RRRef).sp_executesql.Выясним важный нюанс: если ваша цель — увидеть движения товара, гораздо эффективнее обращаться не к табличным частям документов, а к регистрам накопления. В 1С:УПП все движения по номенклатуре стекаются в несколько таблиц (например, «Товары на складах» — _AccumReg123).
Преимущества работы с регистрами:
Если вам сложно разобраться в структуре полей, воспользуемся проверенным методом: запустим SQL Server Profiler, выполним нужный запрос в интерфейсе 1С (например, через консоль запросов 1С или просто сформировав отчет) и «отловим» готовый SQL-текст.
Рассмотрим этот процесс подробнее:
SELECT.Будьте осторожны: запросы, генерируемые платформой 1С, часто перегружены временными таблицами и множественными соединениями. Однако это лучший способ узнать точные имена _Fld для конкретных реквизитов вашей конфигурации.
Важное предостережение: Прямое чтение данных из SQL безопасно для производительности (при наличии индексов), но категорически запрещено изменять данные (INSERT/UPDATE) напрямую в таблицах SQL. Это приведет к нарушению логической целостности базы данных и потере поддержки со стороны вендора.