Как в запросе 1С использовать текущую дату без установки параметра

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

В практике разработчика 1С иногда возникают ситуации, когда стандартный механизм установки параметров запроса через метод УстановитьПараметр() недоступен или крайне неудобен. Это может быть связано с выполнением запроса из внешних систем, использованием специфических DLL или работой в закрытых программных модулях, где мы можем управлять только текстом самого запроса. Однако язык запросов 1С спроектирован так, что в нем отсутствует встроенная функция типа ТекущаяДата() или NOW(), которые привычны пользователям SQL.

В этой статье мы подробно проанализируем ситуацию, выясним причины такого ограничения платформы и разберем все доступные способы решения этой задачи — от динамической подстановки текста до извлечения даты из самой базы данных.

Почему в языке запросов 1С нет функции ТекущаяДата?

Прежде чем мы перейдем к решениям, важно понять архитектурную логику платформы "1С:Предприятие". Язык запросов 1С является декларативным и транслируется сервером приложений в диалект SQL, специфичный для конкретной СУБД (MS SQL Server, PostgreSQL, Oracle или IBM DB2). Платформа активно использует кэширование планов запросов. Если бы внутри текста запроса допускалось использование динамической функции получения времени, это могло бы привести к проблемам с детерминированностью результатов и неэффективному использованию кэша на стороне СУБД.

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

Способ 1: Динамическая подстановка литерала в текст запроса

наиболее очевидный и часто используемый метод — это формирование текста запроса путем склейки строк. Вместо того чтобы использовать имя параметра (например, &Дата), мы вставляем в текст запроса литерал ДАТАВРЕМЯ(...). Это позволяет "зашить" текущую дату непосредственно в команду, которую получит парсер 1С.

Рассмотрим пример реализации на встроенном языке:


// Формируем строковое представление текущей даты в формате литерала 1С
ТекстДаты = "ДАТАВРЕМЯ(" + Формат(ТекущаяДата(), "ДФ=yyyy,MM,dd,HH,mm,ss") + ")";

// Конструируем текст запроса
ТекстЗапроса = "
|ВЫБРАТЬ
|    Сотрудники.Ссылка КАК Сотрудник,
|    КадроваяИстория.ДействуетДо КАК ДатаОкончания
|ИЗ
|    РегистрСведений.КадроваяИсторияСотрудников КАК КадроваяИстория
|ГДЕ
|    КадроваяИстория.ДействуетДо <= " + ТекстДаты;

Важный момент: Хотя этот метод решает проблему отсутствия параметра, он считается нарушением стандартов разработки "1С:Совместимо", так как динамическое формирование текста запроса усложняет его отладку и может привести к ошибкам при неправильном форматировании даты. Используйте его только в тех случаях, когда другие методы (например, СКД) недоступны.

Способ 2: Использование выражений в Системе компоновки данных (СКД)

Если ваш запрос выполняется в рамках отчета или динамического списка, использующего СКД, то проблема решается максимально элегантно. В СКД есть встроенный механизм вычисления выражений для параметров.

  1. Откройте схему компоновки данных и перейдите на закладку Параметры.
  2. Найдите ваш параметр (например, Период или ТекущаяДата).
  3. В колонке Выражение введите текст: ТекущаяДата().
  4. Установите флажок Ограничение доступности, чтобы пользователь не мог изменить это значение вручную.

В этом случае при формировании отчета система сама вычислит текущее время и подставит его в запрос. Вам не придется писать ни одной строчки кода с вызовом УстановитьПараметр().

Способ 3: Особенности виртуальных таблиц (СрезПоследних)

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

Посмотрим на пример запроса:


ВЫБРАТЬ
    КурсыВалютСрезПоследних.Курс,
    КурсыВалютСрезПоследних.Валюта
ИЗ
    РегистрСведений.КурсыВалют.СрезПоследних КАК КурсыВалютСрезПоследних

В данном случае система вернет последние актуальные записи на текущую секунду. Однако стоит помнить, что это работает только для получения среза данных. Если вам нужно сравнить поле даты в основной таблице (как в примере автора с ДействуетДо), этот метод напрямую не поможет.

Способ 4: Получение даты из системных таблиц (метод "якоря")

Рассмотрим наиболее креативный способ: получение текущей даты прямо из базы данных через соединение с таблицами, которые гарантированно обновляются. В конфигурации 1С:Зарплата и Управление Персоналом (ЗУП), о которой шла речь в обсуждении, есть регистры, хранящие информацию об активности пользователей.

Например, в регистре сведений СведенияОПользователях есть поле ДатаПоследнейАктивности. Мы можем извлечь максимальное значение из этого поля и использовать его как суррогат текущей даты.

Проанализируем пример такого запроса:


ВЫБРАТЬ
    МАКСИМУМ(СведенияОПользователях.ДатаПоследнейАктивности) КАК ТекущаяДатаБД
ПОМЕСТИТЬ ВТ_ТекущаяДата
ИЗ
    РегистрСведений.СведенияОПользователях КАК СведенияОПользователях
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    КадроваяИстория.Сотрудник,
    КадроваяИстория.ДействуетДо
ИЗ
    РегистрСведений.КадроваяИсторияСотрудников КАК КадроваяИстория
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ТекущаяДата КАК ВТ_ТекущаяДата
        ПО КадроваяИстория.ДействуетДо <= ВТ_ТекущаяДата.ТекущаяДатаБД

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

Способ 5: Использование функций СУБД (через внешние источники)

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

Пример для прямого SQL-запроса:


SELECT
    _Description,
    _Fld1234 -- Какое-то поле даты
FROM
    _Reference50
WHERE
    _Fld1234 <= GETDATE()

Однако помните, что использование прямых запросов к таблицам 1С (минуя сервер приложений) крайне не рекомендуется, так как это нарушает лицензионное соглашение и может привести к нестабильности системы при обновлении конфигурации.

Резюме и рекомендации

Мы рассмотрели несколько способов обхода ограничения на использование текущей даты в запросах. Подведем итоги, какой метод выбрать в зависимости от ситуации:

  1. Если запрос используется в отчете — всегда используйте выражения параметров в СКД.
  2. Если нужно просто получить актуальные данные из регистра — используйте виртуальные таблицы без указания периода.
  3. Если вы формируете текст запроса программно и нет возможности вызвать УстановитьПараметр() — используйте подстановку литерала ДАТАВРЕМЯ.
  4. В сложных случаях, когда текст запроса должен быть полностью статичным, попробуйте соединение с системными регистрами (например, сведениями об активности пользователей).

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

← На главную