Хранение и повторное использование текстов запросов.

10.07.12

Разработка - Запросы

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

Скачать исходный код

Наименование Файл Версия Размер
Запросы в текстовых макетах.pdf
.pdf 317,54Kb
57
.pdf 317,54Kb 57 Скачать

С появлением 1С версии 8.0, язык запросов получил закономерное развитие. Как известно, разработчики платформы ушли с пути “изобретения велосипеда”, и отказались от собственного механизма запросов с уникальным синтаксисом. Теперь язык запросов в 1С является, по сути, русским (ладно, билингвальным) диалектом SQL. А фирма 1С всячески рекомендует использовать запросы практически для любого извлечения данных.

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

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

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

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

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

В конечном итоге я обратил свой взор на макеты, а именно - на текстовые макеты. Практически все объекты конфигурации (да, не абсолютно все, но очень многие), могут содержать в своих метаданных макеты. Тексты запросов так и просятся, чтобы их размещали в текстовых макетах объекта, если эти запросы имеют отношение исключительно к объекту. Если же запрос носит общий характер для всей конфигурации, имеет смысл сохранить его как один из общих макетов конфигурации.

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

Далее, когда вам нужно выполнить какой-либо запрос, вы просто извлекаете текст нужного запроса конструкцией:

- для случая, когда запрос в макете объекта:

мОбъектЗапроса.Текст = ЭтотОбъект.ПолучитьМакет("ЗапросТаблицаСписокДатПериода").ПолучитьТекст();

- для случая, когда запрос в общем макете конфигурации:

мОбъектЗапроса.Текст = ПолучитьОбщийМакет("ЗапросТаблицаСписокДатПериода").ПолучитьТекст();

- для случая, когда запрос в макете специальной обработки:

мОбъектЗапроса.Текст = Обработки.ЗапросыПодсистемыСклад.ПолучитьМакет("ЗапросВыборкаОстаткиНоменклатуры").ПолучитьТекст();

Если вам нужно построить пакетный запрос, вы просто склеиваете его из разных макетов:

мОбъектЗапроса.Текст = мОбъектЗапроса.Текст +

ЭтотОбъект.ПолучитьМакет("ЗапросВыборкаОстаткиСырьяИГотовойПродукцииНаНачалоПериода").ПолучитьТекст();

Ну, думаю, идея понятна. Хотелось бы немного остановиться на присвоении имен макетам с запросами. Естественно, имена могут быть любыми, и если вы потомок Штирлица, или сотрудник КГБ, вы можете использовать имена типа “З1”, “З2” - смотрите как интересно, русская обфускация - бессмысленная и беспощадная - в действии! Враг точно будет в шоке. Но, для лучшего восприятия кода, я использую такую схему имени:

  1. Слово “Запрос - все макеты, содержащие тексты запросов, начинаются со слова “Запрос”, чтобы можно было отличить их от других макетов.

  2. Таблица” или “Выборка - после слова “Запрос” следует слово “Таблица” или “Выборка”. Слово “Таблица” означает, что запрос содержит команду “Поместить” и возвращает временную таблицу, “Выборка” - соответственно означает, что результат запроса нужно обрабатывать как обычно.

  3. ИмяВременнойТаблицы или Краткое описание выборки - Заканчивается имя макета именем временной таблицы, или кратким описанием содержимого выборки.

 Таким образом, имя макета приобретает, например, вид: "ЗапросТаблицаСписокДатПериода"; встретив его в коде, или увидев в дереве метаданных, мы поймем, что в этом макете содержится текст запроса, результат выполнения которого будет помещен во временную таблицу с именем “СписокДатПериода”.

Открыв этот макет на просмотр, мы увидим:

//Тип запроса: Самостоятельный универсальный

//Требования : Передача параметров ДатаНачалаПериода (Тип "Дата") и ДатаОкончанияПериода (Тип "Дата")

//Результат : Временные таблицы "СписокДатПериода" и "Цифры"

 

ВЫБРАТЬ 0 КАК Цифра ПОМЕСТИТЬ Цифры ОБЪЕДИНИТЬ

ВЫБРАТЬ 1 ОБЪЕДИНИТЬ

ВЫБРАТЬ 2 ОБЪЕДИНИТЬ

ВЫБРАТЬ 3 ОБЪЕДИНИТЬ

ВЫБРАТЬ 4 ОБЪЕДИНИТЬ

ВЫБРАТЬ 5 ОБЪЕДИНИТЬ

ВЫБРАТЬ 6 ОБЪЕДИНИТЬ

ВЫБРАТЬ 7 ОБЪЕДИНИТЬ

ВЫБРАТЬ 8 ОБЪЕДИНИТЬ

ВЫБРАТЬ 9;

 

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ

ДОБАВИТЬКДАТЕ(&ДатаНачалаПериода, ДЕНЬ, СписокДней.Дней) КАК Период

ПОМЕСТИТЬ СписокДатПериода

ИЗ

(ВЫБРАТЬ

СотниТысяч.Цифра * 100000 + ДесяткиТысяч.Цифра * 10000 + Тысячи.Цифра * 1000 + Сотни.Цифра * 100 +

Десятки.Цифра * 10 + Единицы.Цифра КАК Дней

ИЗ

Цифры КАК СотниТысяч

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Цифры КАК ДесяткиТысяч

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Цифры КАК Тысячи

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Цифры КАК Сотни

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Цифры КАК Десятки

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Цифры КАК Единицы

ПО (Единицы.ЦифраРАЗНОСТЬДАТ(&ДатаНачалаПериода, &ДатаОкончанияПериода, ДЕНЬ))

ПО (Десятки.Цифра * 10 РАЗНОСТЬДАТ(&ДатаНачалаПериода, &ДатаОкончанияПериода, ДЕНЬ))

ПО (Сотни.Цифра * 100 РАЗНОСТЬДАТ(&ДатаНачалаПериода, &ДатаОкончанияПериода, ДЕНЬ))

ПО (Тысячи.Цифра * 1000 РАЗНОСТЬДАТ(&ДатаНачалаПериода, &ДатаОкончанияПериода, ДЕНЬ))

ПО (ДесяткиТысяч.Цифра * 10000 РАЗНОСТЬДАТ(&ДатаНачалаПериода, &ДатаОкончанияПериода, ДЕНЬ))

ГДЕ

СотниТысяч.Цифра * 100000 + ДесяткиТысяч.Цифра * 10000 +

Тысячи.Цифра * 1000 + Сотни.Цифра * 100 + Десятки.Цифра * 10 +

Единицы.ЦифраРАЗНОСТЬДАТ(&ДатаНачалаПериода, &ДатаОкончанияПериода, ДЕНЬ)

) КАК СписокДней

;

Отсутствие вертикальных черточек и подсветка синтаксиса повышают восприятие. Копирование в консоль запросов, для отладки, и обратно - тоже упрощается.

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

Нужный запрос будет легко найти, даже просто взглянув на дерево метаданных. Знаете, бывает такое зудящее чувство: “Где-то я писал подобный запрос...”, - как в этом случае у вас продвигались поиски? Я, например, иногда все переписывал заново.

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

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

Можно развить идею и использовать в тексте макета шаблоны, подменяя их перед выполнением запроса. Мне самому пока такая мысль не нравится, я считаю, что лучше использовать два разных макета, - раз уж возникла нужда в разных запросах. Но кто мешает вам попробовать?

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

См. также

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

10000 руб.

02.09.2020    126431    683    389    

737

Пропорциональное распределение в запросе с использованием АвтоНомерЗаписи()

Запросы Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    2351    andrey_sag    10    

29

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    6075    KawaNoNeko    23    

26

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    2176    2    Yashazz    0    

31

Запрос 1С copilot

Инструментарий разработчика Запросы Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

5 стартмани

15.01.2024    6722    32    mkalimulin    27    

53

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

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

14.12.2023    1919    vandalsvq    7    

29

Объектная модель запроса "Схема запроса" 2

Запросы Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Далеко уже не новый тип данных "Схема запроса". Статья о том, как использовать его "попроще". Примеры создания текста запроса с нуля и изменение имеющегося запроса.

06.12.2023    5666    user1923546    26    

46

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    16684    skovpin_sa    14    

101
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
101. juntatalor 63 21.02.13 10:51 Сейчас в теме
Желание структурировать похвально, но в своих конфах использовать не буду, потому что:

а) Нет конструктора запросов. Это настолько существенный минус, что все плюсы от данного нововведения сводит на нет. Чтобы что-то отредактировать, надо ctrl-c куда-то, потом конструктор, потом обратно ctrl-v.
б) Динамически формируемые запросы. Ладно еще, в ГДЕ можно использовать выбор, а, например, в УПОРЯДОЧИТЬ ПО формировать текст надо динамически. Так у меня перед глазами текст запроса, и я сразу вижу что и куда добавляю, не забыл ли я пробел и т.д. Добавлять тьму-тьмущую макетов и потом из них вытягивать, "склеивая" - не вижу смысла, это банально неудобно.

Присоединюсь к (98), язык 1с очень уж напрашивается на ООП. Классов не хватает. Например, то же формирование запросов классами видится очень интересным и перспективным.
99. kasper076 104 27.12.12 08:46 Сейчас в теме
102. Ibrogim 1313 13.01.16 08:42 Сейчас в теме
Метод иногда полезен (с разными вариациями)
Например хранить запросы к другим конфигурациям. при этом пропадает минус отсутствия конструктора (его и так не будет, ведь запрос в другой базе работает например через com)

103. unichkin 1565 01.08.16 09:21 Сейчас в теме
Думаю, настолько подробное рубрицирование скорее избыточно. Я чтобы не загромождать метод текстом запроса - выношу его в функцию, возвращающую строку. Кроме этого сам текст модуля во всех моих разработках всегда структурирован согласно рекомендациям https://its.1c.ru/db/v8std#content:2149184104:hdoc. Я иду немного дальше - блок служебных процедур разбиваю на функциональные блоки, каждый из которых имеет свой префикс (зт - заполнение таблиц, ст - структуры таблиц, тк - тексты запросов... и т. п. ). В общем случае выглядит это так:


////////////////////////////////////////////////////////////­////////////////////////////////////////////////////////////­
// ВнешняяОбработка.ТестЗапроса.МодульОбъекта
//
////////////////////////////////////////////////////////////­////////////////////////////////////////////////////////////­

////////////////////////////////////////////////////////////­////////////////////////////////////////////////////////////­
// ПРОГРАММНЫЙ ИНТЕРФЕЙС

#Область Программный_интерфейс

//==========================================================­========================== Уничкин_РА [01.08.2016 9:16:06]=
Процедура Пример() ЭКСПОРТ
	
	Запрос = Новый Запрос;
	Запрос.Текст = тк_Пример();
	
	РезультатЗапроса = Запрос.Выполнить();
	
	// ... обработка результата запроса
	
КонецПроцедуры
 

#КонецОбласти 


////////////////////////////////////////////////////////////­////////////////////////////////////////////////////////////­
// ОБРАБОТЧИКИ СОБЫТИЙ

//#Область Обработчики_событий

//#КонецОбласти 


////////////////////////////////////////////////////////////­////////////////////////////////////////////////////////////­
// СЛУЖЕБНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ: тексты запросов (тк)

#Область Тексты_запросов

//==========================================================­========================== Уничкин_РА [01.08.2016 9:17:43]=
//Описание: 
// Текст запроса, собирающего таблицу чисел от 0 до 9
//
//Возвращаемое значение:
// Строка - текст запроса 
//
Функция тк_Пример()
	
	Возврат "ВЫБРАТЬ
	        |	1 КАК Поле1
	        |
	        |ОБЪЕДИНИТЬ ВСЕ
	        |
	        |ВЫБРАТЬ
	        |	2
	        |
	        |ОБЪЕДИНИТЬ ВСЕ
	        |
	        |ВЫБРАТЬ
	        |	3
	        |
	        |ОБЪЕДИНИТЬ ВСЕ
	        |
	        |ВЫБРАТЬ
	        |	4
	        |
	        |ОБЪЕДИНИТЬ ВСЕ
	        |
	        |ВЫБРАТЬ
	        |	5
	        |
	        |ОБЪЕДИНИТЬ ВСЕ
	        |
	        |ВЫБРАТЬ
	        |	6
	        |
	        |ОБЪЕДИНИТЬ ВСЕ
	        |
	        |ВЫБРАТЬ
	        |	7
	        |
	        |ОБЪЕДИНИТЬ ВСЕ
	        |
	        |ВЫБРАТЬ
	        |	8
	        |
	        |ОБЪЕДИНИТЬ ВСЕ
	        |
	        |ВЫБРАТЬ
	        |	9
	        |
	        |ОБЪЕДИНИТЬ ВСЕ
	        |
	        |ВЫБРАТЬ
	        |	0";
	
КонецФункции
 
#КонецОбласти 

Показать
Оставьте свое сообщение