Каталог решений - Объект Схема запроса и расширения языка запросов СКД

Объект Схема запроса и расширения языка запросов СКД

Объект Схема запроса и расширения языка запросов СКД

В наличии

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

Категория:

Описание

В дополнение к отличным статьям:

infostart.ru/1c/articles/1222743/

infostart.ru/1c/articles/1453473/

infostart.ru/public/1118622/

про использование объекта «СхемаЗапроса» для редактирования текстов запросов, хочу обратить внимание на один момент.

Я использую объект «СхемаЗапроса» для модификации запросов в типовых конфигурациях. Это, на мой взгляд, самый правильный способ. В типовых конфигурапциях,  как правило, текст запроса формируется в зависимости нескольких условий и функциональных опций и может браться из разных мест в конфигурации. Также разработчики конфигурации используют сложные запросы с несколькими соединениями и если надо, допустим, добавить еще одно, то через функцию СтрЗаменить это сделать достаточно сложно.

Обычно для модификации запроса использую следующий код.

Например, надо в текст запроса надо добавить колонки из нового регистра.

  СхемаЗапроса = Новый СхемаЗапроса;
  СхемаЗапроса.УстановитьТекстЗапроса(ДинамическийСписок.ТекстЗапроса);
  
  ЗапросСхемы = СхемаЗапроса.ПакетЗапросов[0];
  ОператорВыбрать = ЗапросСхемы.Операторы[0];
  
  ВыбираемыеПоля = ОператорВыбрать.ВыбираемыеПоля;
  УсловияОтбора = ОператорВыбрать.Отбор;
  ИсточникОтбора = ОператорВыбрать.Источники[0];		
  
  ПсевдонимОсновнойТаблицы = ИсточникОтбора.Источник.Псевдоним;
  
  // добавление источников
  ИсточникНовыйРегистр = ОператорВыбрать.Источники.Добавить("РегистрСведений.<Регистр_с_которым_соединяем_основную_таблицу>", 
  			"<псевдоним_регистра_в_запросе>");
  
  // по умолчанию, при добавлении источника объект СхемаЗапроса пытается сам установить связи,
  // как правило, неудачно, поэтому очистим их и явно добавим связи
  ИсточникНовыйРегистр.Соединения.Очистить();
  
  // добавление связей
  СоединениеНовыйРегистр = ИсточникОтбора.Соединения.Добавить(ИсточникНовыйРегистр, 
  			СтрШаблон("<псевдоним_регистра_в_запросе>.<реквизит_для_связи_с_основной_таблицей> = %1.Ссылка", ПсевдонимОсновнойТаблицы));
  
  // добавление колонок
  КоличествоКолонок = ЗапросСхемы.Колонки.Количество();
  
  ВыбираемыеПоля.Добавить("<псевдоним_регистра_в_запросе>.<добавляемая_колонка_1>");
  ЗапросСхемы.Колонки[КоличествоКолонок].Псевдоним = "<псевдоним_добавляемой_колонки_1>";
  КоличествоКолонок = КоличествоКолонок + 1; 
  
  ВыбираемыеПоля.Добавить("<псевдоним_регистра_в_запросе>.<добавляемая_колонка_2>");
  ЗапросСхемы.Колонки[КоличествоКолонок].Псевдоним = "<псевдоним_добавляемой_колонки_2>";
  КоличествоКолонок = КоличествоКолонок + 1; 
  
  ТекстЗапроса = СхемаЗапроса.ПолучитьТекстЗапроса();		
  
  ДинамическийСписок.ТекстЗапроса = ТекстЗапроса;
  

Все отлично работает, но если в запросе не присутствуют расширения языка запросов СКД. В этом случае так запрос отличается от сделанного «вручную». Пример взят из конфигурации 1С:Документооборот.

  {ГДЕ
  	(ЗадачаИсполнителя.Выполнена = &Выполнена) КАК Поле2,
  	(ЗадачаИсполнителя.СрокИсполнения < &ДатаДляОтображенияПросроченных
  			И ЗадачаИсполнителя.СрокИсполнения > ДАТАВРЕМЯ(1, 1, 1)) КАК Поле4,
  	(ЗадачаИсполнителя.ПринятаКИсполнению = &ОтображатьСтарыеЗадачи) КАК Поле6,
  	(ЗадачаИсполнителя.Автор = &Автор) КАК Поле8,
  	(ЗадачаИсполнителя.Проект = &Проект) КАК Поле10}

В текст запроса добавляются автоматические созданные псевдонимы "Поле2", "Поле4" и т.д.

И такая вставка приводи к ошибке времени выполнения.

Видимо, расширение языка запроса СКД появилось позже чем объект «СхемаЗапроса». И авторы расширения запросов СКД старались сделать, чтобы это расширение было максимально совместимым с тем, что создано до этого. Но этот момент остался вне их внимания.

Для исправления ситуации я добавляю следующий код.

  // нужно очистить псевдонимы выражений отбора компоновки данных, иначе генерится запрос
  // с псевдонимами, который приводит к ошибке исполнения.
  Для каждого ВыражениеОтбора Из ОператорВыбрать.ВыраженияОтбораКомпоновкиДанных Цикл
  	ВыражениеОтбора.Псевдоним = "";
  КонецЦикла;

И итоге, получаем следующий код:

  СхемаЗапроса = Новый СхемаЗапроса;
  СхемаЗапроса.УстановитьТекстЗапроса(ДинамическийСписок.ТекстЗапроса);
  
  ЗапросСхемы = СхемаЗапроса.ПакетЗапросов[0];
  ОператорВыбрать = ЗапросСхемы.Операторы[0];
  
  ВыбираемыеПоля = ОператорВыбрать.ВыбираемыеПоля;
  УсловияОтбора = ОператорВыбрать.Отбор;
  ИсточникОтбора = ОператорВыбрать.Источники[0];		
  
  ПсевдонимОсновнойТаблицы = ИсточникОтбора.Источник.Псевдоним;
  
  // добавление источников
  ИсточникНовыйРегистр = ОператорВыбрать.Источники.Добавить("РегистрСведений.<Регистр_с_которым_соединяем_основную_таблицу>", 
  			"<псевдоним_регистра_в_запросе>");
  
  // по умолчанию, при добавлении источника объект СхемаЗапроса пытается сам установить связи,
  // как правило, неудачно, поэтому очистим их и явно добавим связи
  ИсточникНовыйРегистр.Соединения.Очистить();
  
  // добавление связей
  СоединениеНовыйРегистр = ИсточникОтбора.Соединения.Добавить(ИсточникНовыйРегистр, 
  			СтрШаблон("<псевдоним_регистра_в_запросе>.<реквизит_для_связи_с_основной_таблицей> = %1.Ссылка", ПсевдонимОсновнойТаблицы));
  
  // добавление колонок
  КоличествоКолонок = ЗапросСхемы.Колонки.Количество();
  
  ВыбираемыеПоля.Добавить("<псевдоним_регистра_в_запросе>.<добавляемая_колонка_1>");
  ЗапросСхемы.Колонки[КоличествоКолонок].Псевдоним = "<псевдоним_добавляемой_колонки_1>";
  КоличествоКолонок = КоличествоКолонок + 1; 
  
  ВыбираемыеПоля.Добавить("<псевдоним_регистра_в_запросе>.<добавляемая_колонка_2>");
  ЗапросСхемы.Колонки[КоличествоКолонок].Псевдоним = "<псевдоним_добавляемой_колонки_2>";
  КоличествоКолонок = КоличествоКолонок + 1; 
  
  // нужно очистить псевдонимы выражений отбора компоновки данных, иначе генерится запрос
  // с псевдонимами, который приводит к ошибке исполнения.
  Для каждого ВыражениеОтбора Из ОператорВыбрать.ВыраженияОтбораКомпоновкиДанных Цикл
  	ВыражениеОтбора.Псевдоним = "";
  КонецЦикла;
  
  ТекстЗапроса = СхемаЗапроса.ПолучитьТекстЗапроса();		
  
  ДинамическийСписок.ТекстЗапроса = ТекстЗапроса;
  

В этом случае получаемый тест запрос идентичен такому же запросу, написанному вручную или через конструктор запроса.

Надеюсь, будет полезно. Спасибо за внимание!

has been added to your cart:
Оформление заказа