Как отобрать непроведенные документы в запросе к внешнему источнику данных 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции двух информационных баз 1С разработчики нередко используют механизм внешних источников данных для прямого чтения таблиц СУБД (например, Microsoft SQL Server) соседней базы. Однако при попытке отфильтровать документы по признаку проведения стандартными методами языка запросов 1С часто возникают ошибки.

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


ВЫБРАТЬ ПЕРВЫЕ 10
    Док._Number,
    Док._DateTime
ИЗ
    ВнешнийИсточникДанных.аВнешняяБаза.Таблица.ПоступлениеНаРасчетныйСчет КАК Док
ГДЕ
    Док._Posted = &НеПроведен

При попытке передать в параметр значение Ложь, написать напрямую ГДЕ Док._Posted = Ложь или использовать отрицание ГДЕ НЕ Док._Posted платформа возвращает системные ошибки: «Операция не разрешена в предложении "ГДЕ"» или «Неверные параметры "НЕ"». Попытка явного приведения через ВЫРАЗИТЬ(Док._Posted КАК Булево) также терпит неудачу с ошибкой «Несовместимые типы "ВЫРАЗИТЬ"».

Проанализируем причины такого поведения платформы и рассмотрим правильные способы настройки внешнего источника данных.

Почему возникает ошибка: специфика хранения данных в СУБД 1С

Выясним причину проблемы. В СУБД (в частности, Microsoft SQL Server) служебные логические реквизиты документов 1С — такие как признак проведения _Posted и пометка удаления _Marked — физически хранятся не в логическом типе bit, а в бинарном формате binary(1). Непроведенному документу соответствует значение 0x00, а проведенному — 0x01.

Когда мы добавляем таблицу через мастер внешних источников данных конфигуратора, драйвер СУБД считывает метаданные таблицы напрямую. Видя тип binary(1), платформа 1С автоматически сопоставляет его с типом ДвоичныеДанные. Для полей с таким типом на уровне языка запросов 1С операции сравнения в условии ГДЕ, логические операторы и приведение типов полностью заблокированы.

Основное решение: изменение типа поля в дереве метаданных

Для исправления ситуации не нужно писать сложные SQL-запросы или преобразовывать типы вручную в коде. Достаточно скорректировать описание типа поля в свойствах внешнего источника данных.

Разберем по шагам, как это сделать:

  1. Откроем конфигуратор информационной базы.
  2. В дереве метаданных развернем ветку Внешние источники данных и найдем нужное подключение к базе.
  3. Перейдем в ветку Таблицы, выберем нужную таблицу документа (например, ПоступлениеНаРасчетныйСчет) и откроем список её полей.
  4. Найдем служебное поле _Posted и откроем палитру свойств.
  5. В свойстве Тип снимем флаг с типа ДвоичныеДанные и выберем тип Булево.
  6. Сохраним изменения и обновим конфигурацию базы данных.

После назначения поля типом Булево платформа 1С берет на себя трансляцию условий: конструкции сравнения автоматически преобразуются в корректные бинарные литералы СУБД (0x00 и 0x01).

Посмотрим на пример рабочего запроса после изменения типа поля:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 10
    |   Док._Number КАК Номер,
    |   Док._DateTime КАК Дата,
    |   Док._Posted КАК Проведен
    |ИЗ
    |   ВнешнийИсточникДанных.аВнешняяБаза.Таблица.ПоступлениеНаРасчетныйСчет КАК Док
    |ГДЕ
    |   Док._Posted = ЛОЖЬ";

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Также корректно будут работать условия вида ГДЕ НЕ Док._Posted и передача параметра Ложь в запрос.

Альтернативный вариант: назначение числового типа

Рассмотрим еще один допустимый способ обхода проблемы. Если по каким-то причинам использование логического типа нежелательно, для поля _Posted в метаданных внешнего источника можно задать тип Число с длиной 1 и точностью 0.

В этом случае бинарные значения 0x00 и 0x01 будут считываться как числа 0 и 1. В тексте запроса фильтрация по непроведенным документам будет выглядеть следующим образом:


ВЫБРАТЬ ПЕРВЫЕ 10
    Док._Number КАК Номер,
    Док._DateTime КАК Дата
ИЗ
    ВнешнийИсточникДанных.аВнешняяБаза.Таблица.ПоступлениеНаРасчетныйСчет КАК Док
ГДЕ
    Док._Posted = 0

Подводные камни прямого чтения таблиц 1С через внешние источники

При работе с сырыми таблицами базы 1С через внешние источники данных обратим внимание на важные технические нюансы:

  1. Смещение дат: в СУБД Microsoft SQL Server даты документов 1С по умолчанию могут храниться со смещением в 2000 лет для совместимости с ранними версиями платформ. В поле _DateTime год может отображаться со значением 4024 вместо 2024. Это необходимо учитывать при обработке результатов или наложении фильтров по периоду.
  2. Нестабильность структуры: имена служебных реквизитов (например, табличные части или пользовательские реквизиты вида _Fld1234) формируются динамически. При обновлении конфигурации базы-источника или реструктуризации таблиц идентификаторы полей могут измениться, что приведет к потере работоспособности внешнего источника данных.

Альтернативные способы интеграции

Если прямое чтение таблиц SQL вызывает регулярные сложности с типами данных и структурой, рассмотрим более надежные архитектурные варианты решения:

  1. Создание SQL View (представления) в базе-источнике: на стороне СУБД можно создать представление, где типы будут приведены штатными функциями базы данных (например, CAST(_Posted AS bit)) и скорректировано смещение дат. Внешний источник данных в 1С при этом подключается не к сырой таблице, а к готовому представлению.
  2. Использование стандартного OData-интерфейса: если база-источник опубликована на веб-сервере, данные можно получать по протоколу OData через HTTP-запросы. Фильтрация непроведенных документов в этом случае выполняется штатным параметром $filter=Posted eq false без работы со спецификой SQL-хранилища.
  3. COM-соединение или HTTP-сервисы: подключение через V83.COMConnector или обращение к собственному HTTP-сервису базы-источника позволяет выполнять запросы на родном языке 1С в терминах объектов метаданных (Документ.ПоступлениеНаРасчетныйСчет), полностью абстрагируясь от внутреннего устройства таблиц базы данных.
← На главную