Модель запроса SQL

23.08.23

Разработка - Инструментарий разработчика

Следующее решение является развитием модели запроса 1С. В этой модели конструируется запрос на SQL с использованием таблиц БД на 1С и внешних источников. Можно использовать все типы запросов: выборка, изменение, удаление. В качестве источника данных можно указать таблицу значений. Работать с запросом SQL из 1С никогда еще не было так просто! :)

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

Наименование Файл Версия Размер
Демо база
.dt 123,91Mb
7
.dt 1.0.2 123,91Mb 7 Скачать
Конфигурация "Модель запроса SQL"
.cf 149,68Kb
11
.cf 1.0.2 149,68Kb 11 Скачать

Оглавление

Введение. 1

Запрос SQL. 2

Имена таблиц и полей хранения в БД. 2

Типы запросов. 2

Работа с ADODB. 2

Схема БД. 3

Получение текста запроса SQL. 3

Результат запроса ADODB. Таблица в формате JSON.. 4

Значения предопределенных данных и использование имен 1С. 4

Бинарные значения. 4

Значения ссылки. 4

Значения даты. 5

Имя поля хранения. 5

Предопределенные значения

Значения пустой ссылки, Неопределено

. 5

Перечисления. 5

Работа с временными таблицами. 6

Создание временной таблицы. 6

Временная таблица из объекта с данными. 6

Уничтожение таблицы. 6

Агрегатные функции

Запросы на удаление и изменение. 6

Запрос на удаление строк. 6

Запрос на изменение. 6

Работа в клиент/серверном режиме. 7

Конструктор модели запроса SQL

Демо-пример сценария использования модели запроса SQL

Поставка. 7


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

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

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

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

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

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

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

На входе модель принимает имя таблицы источника и ее псевдоним. Таблица источника может быть распознана как таблица 1С и тогда для нее определяется имя хранения таблицы и её полей в БД. Обращение к полям таблицы 1С можно сделать через рекурсивный вызов функции самой модели. Т.к. модель распознает таблицы 1С, то имя поля хранения можно получить из самой модели и вернуть его в условие отбора или в выражение выбранного поля модели. Иными словами, если в модели уже была использована таблица 1С, то модель уже "знает" имя хранения таблицы и ее полей в БД.

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

Конечно, использование запросов, минуя объектную модель 1С может привести к последствиям. Поэтому нужно иметь очень веские основания для использования запросов на изменение к данным, хранящимся в базе 1С. Это могут быть задачи восстановления, тестирования, сверки, конвертации или еще какой-либо разовой обработки данных.

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

Выполнение запроса SQL из 1С можно сделать например через объект ADODB. Для это достаточно создать объект и настроить соединение с базой. Использовать объект можно как на клиенте, так и на сервере. Для меня особый интерес представлял клиентский режим работы, т.к. я использовал win-аутентификацию на клиенте вместо служебного пользователя на сервере.

Для работы с ADODB был создан общий модуль РаботаС_ADODB. Основное назначение модуля: интерпретировать входящие параметры подключения в формат соединения ADODB и выдавать результат запроса в обработанном виде.

Для настройки соединения необходимо указать Сервер БД и Имя базы данных, а также параметры аутентификации. ADODB работает не с отдельными параметрами соединения, а со строкой соединения. Строка соединения имеет свой формат, справочник по формату подключения к MS SQL можно посмотреть здесь https://www.connectionstrings.com/sql-server/. Есть еще интерфейсный способ конструирования строки подключения, который можно вызвать кодом на 1С (см. Пример в //infostart.ru/1c/articles/80730/). В модели РаботаС_ADODB соединение к БД получается из переданных  параметров подключения.

Для работы с результатом запроса через ADODB необходимо его загрузить в какой нибудь тип данных. Таблица значений не подходит, т.к. нужно также обеспечить работу и на клиенте. Устоявшегося формата для хранения типизированных табличных данных, кроме таблицы значений - в платформе нет. Можно смоделировать таблицу в виде структуры со свойствами: Колонки, Строки. Колонки - массив структур со свойствами колонки, а строки - массив строк, где каждая строка - массив значений.

Также необходимо решить вопрос с преобразованием типов данных ADODB в соответствующие типы 1С. Простые типы: Строка, Число, Дата - необходимо интерпретировать по размеру, точностью, формату времени и даты. Тип Булево и ссылки 1С хранит в бинарном типе. При чтении полей с бинарным типом ADODB возвращает массив байтов COMSafeArray. Этот массив необходимо преобразовать в соответствующий тип: Булево, Ссылка.

При выполнении пакета запросов ADODB также возвратит пакет результатов. В модуле есть две функции выполнения запроса по аналогии с запросом 1С: ВыполнитьЗапрос(ТекстЗапросаSQL), ВыполнитьПакетЗапросов(ТекстЗапросаSQL) - в первом будет возвращен результат последнего запроса, а во втором - массив результатов.

В одной БД может существовать неограниченное количество таблиц с одинаковыми именами. Для обеспечения уникальности таблиц в БД используются пространства имен. Пространство задается указанием схемы. Обычно схема имеет имя своего владельца. Например для таблиц 1С обычно указывается владелец dbo и для указания таблицы 1С требуется указывать префикс dbo (если имя таблицы в БД однозначно, то можно и не указывать).

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

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

Если вы еще не знакомы с моделью запроса, то рекомендую познакомиться прежде, чем читать дальше :)

Для тех, кто знаком с моей разработкой Модель запроса, представленный способ работы с запросами SQL будет также понятен. Здесь и далее я буду пользоваться обработкой "Конструктор модели запроса SQL".

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

 

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

 

Исследуйте полученный текст запроса на SQL. При желании его можно тут же и выполнить по команде "Выполнить запрос". Результат выполнения можно увидеть в формате JSON. По команде "Печать" результат можно вывести в табличный отчет.

В текущей версии модель может быть использована только для получения текста запроса SQL и работает в контексте Сервера. Выполнение запроса и обработка результата доступна в разных контекстах через использование функций модуля РаботаС_ADODB.

Для работы с результатом запроса я разработал следующий формат таблицы результата: {Колонки: [{Имя, ТипЗначения}, ...], Строки: [[,,,,], ...]}. Соответствующий тип в 1С - это Структура с полями Колонки, Строки. Колонки - массив структур с полями Имя, ТипЗначения. Строки - массив строк, где строка - массив значений колонок. Такая структура хорошо сериализуется в формат JSON и с ней можно работать в разных контекстах клиент/сервер.

Для описания типа я принял следующий формат: СТРОКА(n), ЧИСЛО(n, m), ДАТА, БУЛЕВО, где описание размера и точности можно опустить.

Например для следующей модели запроса:

;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
МодельЗапроса.ЗапросПакета()
    .Выбрать().Первые(3)
        .Источник("Документ._ДемоЗаказПокупателя")
        .Поле("_ДемоЗаказПокупателя.Ссылка")
        .Поле("_ДемоЗаказПокупателя.Дата")
        .Поле("_ДемоЗаказПокупателя.Номер")
        .Поле("_ДемоЗаказПокупателя.ПометкаУдаления")
;

получим следующий текст запроса SQL:

-- ЗАПРОС ПАКЕТА 1. _ДемоЗаказПокупателя
SELECT TOP 3
	_ДемоЗаказПокупателя._IDRRef AS Ссылка
	, _ДемоЗаказПокупателя._Date_Time AS Дата
	, _ДемоЗаказПокупателя._Number AS Номер
	, _ДемоЗаказПокупателя._Marked AS ПометкаУдаления
FROM
    _Document39 AS _ДемоЗаказПокупателя

и результат выполнения запроса:

{
 "Колонки": [
  {
   "Имя": "Ссылка",
   "ТипЗначения": "СТРОКА(34)"
  },
  {
   "Имя": "Дата",
   "ТипЗначения": "СТРОКА(19)"
  },
  {
   "Имя": "Номер",
   "ТипЗначения": "СТРОКА(11)"
  },
  {
   "Имя": "ПометкаУдаления",
   "ТипЗначения": "СТРОКА(4)"
  }
 ],
 "Строки": [
  [
   "0x896CE0CB4ED5F65511E4A2D5A2EB6C9C",
   "4015-01-23 11:03:58",
   "00-00000018",
   "0x00"
  ],
  [
   "0x8C3608002700700111E1CA6CC5F6A3F7",
   "4011-12-12 10:45:05",
   "00-00000002",
   "0x00"
  ],
  [
   "0x8C3608002700700111E1CA6CC5F6A3F8",
   "4012-03-23 11:57:31",
   "00-00000003",
   "0x00"
  ]
 ]
}

По команде Печать получим такой отчет:

 

 

В таблице результата можно заметить, что типы полей строковые. Такая особенность работы с типами данных из БД 1С: тип Булево хранится в бинарном виде, тип Дата возвращается из ADO как строковый, а ссылка хранится в бинарном виде 16 слов. Подробнее про работу с типами я описал ниже.

Для различных преобразований результата есть функции из общих модулей:

JSON = ОбщийКлиентСервер.ОбъектВJSON(ТаблицаJSON);
ТаблицаJSON = ОбщийКлиентСервер.JSONВОбъект(JSON);

Взаимные преобразования ТаблицаJSON->JSON и JSON->ТаблицаJSON

ТаблицаJSON = Общий.ТаблицаЗначенийВСтруктуру(ТаблицаЗначения);
ТаблицаЗначения = Общий.СтруктураВТаблицуЗначений(ТаблицаJSON);

Взаимные преобразования ТаблицаЗначения->ТаблицаJSON и ТаблицаJSON ->ТаблицаЗначения

Значения предопределенных данных и использование имен 1С

В структуре данных базы 1С типы Булево и Ссылка хранятся в бинарных полях.

В текущей версии формата таблицы результата бинарные поля не поддерживаются прямо. При обработке значений таких полей интерпретируются в виде бинарного числа в шетнадцатиричном формате. Хранится такое значение в поле типа Строка соответствующего размера + 2, где два символа отводятся на префикс "0x". При интерпретации запроса из источника, значения с таким префиксом интерпретируются как бинарные числа.

Например напишем слудующий текст модели выборки результата:

;//  ЗАПРОС ПАКЕТА.
МодельЗапроса.ЗапросПакета("_ДемоЗаказПокупателя")
    .Выбрать().Первые(3)
        .Источник(Результат, "Результат")
        .Поле("Ссылка")
        .Поле("Дата")
        .Поле("Номер")
        .Поле("ПометкаУдаления")
;

по команде Получить текст запроса получится следующий SQL запрос из результата выполнения предыдущего запроса:

-- ЗАПРОС ПАКЕТА 1. _ДемоЗаказПокупателя
SELECT TOP 3
    Ссылка AS Ссылка
    , Дата AS Дата
    , Номер AS Номер
    , ПометкаУдаления AS ПометкаУдаления
FROM
    (VALUES
        (0x896CE0CB4ED5F65511E4A2D5A2EB6C9C, '4015-01-23 11:03:58', '00-00000018', 0x00)
        , (0x8C3608002700700111E1CA6CC5F6A3F7, '4011-12-12 10:45:05', '00-00000002', 0x00)
        , (0x8C3608002700700111E1CA6CC5F6A3F8, '4012-03-23 11:57:31', '00-00000003', 0x00)
    ) AS Результат (Ссылка, Дата, Номер, ПометкаУдаления)

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

Значения ссылки

Ссылки или ИД объектов 1С хранятся в бинарном поле размером 16 двухбайтовых слов. Особенность работы с таким типом в том, что интерпретация значения ссылки в БД и в коде 1С различаются. В БД ссылка хранится в бинарном виде и представляется как шестнадцатиричное число. В коде 1С ссылка имеет особое представление в шестнадцатиричном виде. Т.е. это тоже самое число, но порядок байтов другой, не от старшего к младшему, а особый.

В модуле есть две функции преобразования: HexToBin - порядок представления ссылки в 1С -> бинарное представление в БД, BinToHex - бинарное представление в БД -> шестнадцатиричное представление ссылки в 1С.

Если получить результат запроса, то в нем будет представление в БД. Такое представление можно использовать без преобразования в других запросах к БД. Однако чтобы по такому значению найти ссылку средствами 1С необходимо его преобразовать в шестнадцатиричное представление 1С. И наоборот, чтобы по представлению ссылки из 1С найти значение ссылки в запросе SQL ее нужно преобразовать в бинарный формат шестнадцатиричного представления в БД.

Значение даты 1С хранит в полях с типом данных datetime2. Это предпочтительный тип хранения даты, но при чтении через ADO значения таких полей интерпретируются как строковые.

Проблем с чтением типа datetime нет. Значения этого типа читаются как дата и время.

Для решения проблемы чтения типа datetime2 можно использовать следующее преобразование к типу datetime: CAST(DATEADD(YYYY, -2000, ИмяПоляХранения) AS DATETIME) AS Псевдоним.

Исправим поле в уже приведенном примере модели (не забываем указывать псевдоним поля, т.к. псевдоним по умолчанию от выражения может содержать ошибки):

;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
МодельЗапроса.ЗапросПакета("_ДемоЗаказПокупателя")
    .Выбрать().Первые(3)
        .Источник("Документ._ДемоЗаказПокупателя")
        .Поле("_ДемоЗаказПокупателя.Ссылка")
        .Поле(СтрШаблон("CAST(DATEADD(YYYY, -2000, %1) AS DATETIME)", МодельЗапроса.ИмяПоляХранения("_ДемоЗаказПокупателя.Дата")), "Дата")
        .Поле("_ДемоЗаказПокупателя.Номер")
        .Поле("_ДемоЗаказПокупателя.ПометкаУдаления")
;

полученный текст SQL:

-- ЗАПРОС ПАКЕТА 1. _ДемоЗаказПокупателя
SELECT TOP 3
	_ДемоЗаказПокупателя._IDRRef AS Ссылка
	, CAST(DATEADD(YYYY, -2000, _ДемоЗаказПокупателя._Date_Time) AS DATETIME) AS Дата
	, _ДемоЗаказПокупателя._Number AS Номер
	, _ДемоЗаказПокупателя._Marked AS ПометкаУдаления
FROM
	_Document39 AS _ДемоЗаказПокупателя

и полученный результат:

{
 "Колонки": [
  {
   "Имя": "Ссылка",
   "ТипЗначения": "СТРОКА(34)"
  },
  {
   "Имя": "Дата",
   "ТипЗначения": "ДАТА"
  },
  {
   "Имя": "Номер",
   "ТипЗначения": "СТРОКА(11)"
  },
  {
   "Имя": "ПометкаУдаления",
   "ТипЗначения": "СТРОКА(4)"
  }
 ],
 "Строки": [
  [
   "0x896CE0CB4ED5F65511E4A2D5A2EB6C9C",
   "2015-01-23T11:03:58",
   "00-00000018",
   "0x00"
  ],
  [
   "0x8C3608002700700111E1CA6CC5F6A3F7",
   "2011-12-12T10:45:05",
   "00-00000002",
   "0x00"
  ],
  [
   "0x8C3608002700700111E1CA6CC5F6A3F8",
   "2012-03-23T11:57:31",
   "00-00000003",
   "0x00"
  ]
 ]
}

, где тип поля - Дата, формат даты в ISO и учтено смещение -2000.

Отмечу также, что для обратного преобразования достаточно добавить к значению поля datetime смещение 2000 вот так: DATEADD(YYYY, 2000, ИмяПоля). Такие значения можно использовать в выражениях сравнения или для обновления данных в базе 1С.

Имя поля хранения

Простые преобразования полей 1С в поля хранения производятся сразу. Если в модели явно задан источник - таблица 1С и через точку поле из этого источника, то модель запроса SQL преобразует такое поле в имя поля хранения с псевдонимом имени поля. Например Поле("_ДемоЗаказПокупателя.Ссылка") будет преобразовано в _IDRRef AS Ссылка. Однако выражение поля Поле("SUM(Товары.Количество)") уже преобразовано не будет. Для преобразования такого поля нужно использовать функцию модели ИмяПоляХранения(ПутьКПолю). Приведенный код будет выглядеть так:

Поле(СтрШаблон("SUM(%1)", МодельЗапросаSQL.ИмяПоляХранения("Товары.Количество")))

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

Использование в запросе значений перечислений или предопределенных значений реализовано через использование функции модели ИД(ПредопределенноеЗначение). Предопределенное значение можно использовать в выражении поля, отбора, условий связи или в выражении порядка.

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

;//  ЗАПРОС ПАКЕТА.
МодельЗапроса.ЗапросПакета()
    .Выбрать()
        .Источник("Справочник._ДемоФизическиеЛица.КонтактнаяИнформация", "КонтактнаяИнформация")
        .Источник("Справочник._ДемоФизическиеЛица")
        .ЛевоеСоединение("КонтактнаяИнформация", "_ДемоФизическиеЛица")
            .Связь("Ссылка")
        .Отбор(СтрШаблон("%1 = %2", МодельЗапроса.ИмяПоляХранения("КонтактнаяИнформация.Тип"), МодельЗапроса.ИД(Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты)))
        .Отбор(СтрШаблон("%1 = %2", МодельЗапроса.ИмяПоляХранения("КонтактнаяИнформация.Вид"), МодельЗапроса.ИД(Справочники.ВидыКонтактнойИнформации.EmailПользователя)))
        .Поле("_ДемоФизическиеЛица.Ссылка")
        .Поле("КонтактнаяИнформация.НомерСтроки")
        .Поле("КонтактнаяИнформация.Тип")
        .Поле("КонтактнаяИнформация.Вид")
        .Поле("КонтактнаяИнформация.Значение")
;

Использование полей хранения и предопределенных значений в условиях отбора

-- ЗАПРОС ПАКЕТА 1.
SELECT 
    _ДемоФизическиеЛица._IDRRef AS Ссылка
    , КонтактнаяИнформация._LineNo4843 AS НомерСтроки
    , КонтактнаяИнформация._Fld4844RRef AS Тип
    , КонтактнаяИнформация._Fld4845RRef AS Вид
    , КонтактнаяИнформация._Fld6754 AS Значение
FROM
    _Reference38_VT4842 AS КонтактнаяИнформация
        LEFT JOIN _Reference38 AS _ДемоФизическиеЛица
        ON КонтактнаяИнформация._Reference38_IDRRef = _ДемоФизическиеЛица._IDRRef
WHERE
    КонтактнаяИнформация._Fld4844RRef = 0x82E6D573EE35D0904BF4D326A84A91D2
     AND КонтактнаяИнформация._Fld4845RRef = 0xA6974B87E83C8DD04F784C2BB930F2D1

Текст запроса SQL, полученные из модели

Значения ПустаяСсылка, Неопределено

Значения пустой ссылки или значения Неопределено в SQL одно - это бинарный ноль: 0x00000000000000000000000000000000. Для подстановки такого значения в модель можно воспользоваться функцией ИД() без аргумента или с пустым значением. Эта функция для любого пустого значения или Неопределено вернет бинарное представление ноля.

;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
МодельЗапроса.ЗапросПакета("_ДемоЗаказПокупателя")
    .Выбрать()
        .Источник("Документ._ДемоЗаказПокупателя")
        .Поле("_ДемоЗаказПокупателя.Номер")
        .Поле("_ДемоЗаказПокупателя.Дата")
        .Поле("_ДемоЗаказПокупателя.Организация")
        .Поле("_ДемоЗаказПокупателя.Контрагент")
        .Поле("_ДемоЗаказПокупателя.Договор")
        .Поле("_ДемоЗаказПокупателя.Проведен")
        .Поле("_ДемоЗаказПокупателя.ПометкаУдаления")
        .Отбор(СтрШаблон("%1 = %2", МодельЗапроса.ИмяПоляХранения("_ДемоЗаказПокупателя.Договор"), МодельЗапроса.ИД()))
;

Отбор заказов по пустому значению договора

-- ЗАПРОС ПАКЕТА 1. _ДемоЗаказПокупателя
SELECT 
    _ДемоЗаказПокупателя._Number AS Номер
    , _ДемоЗаказПокупателя._Date_Time AS Дата
    , _ДемоЗаказПокупателя._Fld968RRef AS Организация
    , _ДемоЗаказПокупателя._Fld2908RRef AS Контрагент
    , _ДемоЗаказПокупателя._Fld2909RRef AS Договор
    , _ДемоЗаказПокупателя._Posted AS Проведен
    , _ДемоЗаказПокупателя._Marked AS ПометкаУдаления
FROM
    _Document39 AS _ДемоЗаказПокупателя
WHERE
    _ДемоЗаказПокупателя._Fld2909RRef = 0x00000000000000000000000000000000

SQL запрос с отбором по пустой ссылке

{
 "Колонки": [
  {
   "Имя": "Номер",
   "ТипЗначения": "СТРОКА(11)"
  },
  {
   "Имя": "Дата",
   "ТипЗначения": "СТРОКА(19)"
  },
  {
   "Имя": "Организация",
   "ТипЗначения": "СТРОКА(34)"
  },
  {
   "Имя": "Контрагент",
   "ТипЗначения": "СТРОКА(34)"
  },
  {
   "Имя": "Договор",
   "ТипЗначения": "СТРОКА(34)"
  },
  {
   "Имя": "Проведен",
   "ТипЗначения": "СТРОКА(4)"
  },
  {
   "Имя": "ПометкаУдаления",
   "ТипЗначения": "СТРОКА(4)"
  }
 ],
 "Строки": [
  [
   "00-00000019",
   "4015-07-24 10:46:36",
   "0x00000000000000000000000000000000",
   "0x00000000000000000000000000000000",
   "0x00000000000000000000000000000000",
   "0x00",
   "0x00"
  ]
 ]
}

Результат запроса: найден один заказ, у которого не заполнены Организация, Контрагент, Договор

Работа с перечислениями несколько отличается от работы с предопределенными значениями других видов метаданных. Дело в том, что перечисления - это именованные константы, ссылки на которые хранятся в конфигурации, а не в БД.

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

В модели запроса SQL можно использовать перечисления наравне с другими предопределенными значениями. Модель использует сохраненное соответствие именованной константы перечисления и ее идентификатора в макете "Перечисления". Текст макета можно получить по команде "Конструктора модели запроса SQL" - "Макет "Перечисления"".

В большинстве случаев у вас не должно возникнуть проблем в получении макета. Обработка позволяет извлечь данные перечислений как с использованием конфигуратора (режим Конфигуратор), так и из файлов выгрузки (формат EDT/XML). При работе через конфигуратор нужно иметь в виду, что среди действующих расширений не должно быть расширений для перечислений. Это единственное ограничение, которое я обнаружил. Обойти его можно либо выключив предварительно такие расширения, либо через выгрузку файлов.

 

Обработка получения макета "Перечисления"

 

Процесс описания создания временной таблицы аналогичен как в модели запроса. Делается это оператором Поместить(ИмяВременнойТаблицы). Имя временной таблицы следует начинать с символа #. Если же использовать обычное имя таблицы, то тогда такая таблица будет создана в базе и уже не будет временной.

Есть еще один вариант создания временной таблицы, так называемая таблица локального использования. Это что-то типа вложенного запроса с именем. Использование такого варианта временной таблицы имеет свои ограничения, но иногда более оптимально. Оператор для такой таблицы будет: Использовать(ИмяВременногоЗапроса).

;//  ЗАПРОС ПАКЕТА. #ВТ_ЗАКАЗЫ
МодельЗапроса.ЗапросПакета().Поместить("#ВТ_ЗАКАЗЫ")
    .Выбрать()
        .Источник("Документ._ДемоЗаказПокупателя")
        .Отбор(СтрШаблон("%1 = 0", МодельЗапроса.ИмяПоляХранения("_ДемоЗаказПокупателя.Проведен")))
        .Поле("_ДемоЗаказПокупателя.Ссылка")
        .Поле("_ДемоЗаказПокупателя.Проведен")
        .Поле("_ДемоЗаказПокупателя.ПометкаУдаления")
;//  ЗАПРОС ПАКЕТА. ВТ_ЗАКАЗЫ
МодельЗапроса.ЗапросПакета("ВТ_ЗАКАЗЫ")
    .Выбрать()
        .Источник("#ВТ_ЗАКАЗЫ", "ВТ_ЗАКАЗЫ")
        .Поле("ВТ_ЗАКАЗЫ.Ссылка")
        .Поле("ВТ_ЗАКАЗЫ.Проведен")
        .Поле("ВТ_ЗАКАЗЫ.ПометкаУдаления")
;

Модель создания временной таблицы

-- ЗАПРОС ПАКЕТА 1. #ВТ_ЗАКАЗЫ
SELECT 
    _ДемоЗаказПокупателя._IDRRef AS Ссылка
    , _ДемоЗаказПокупателя._Posted AS Проведен
    , _ДемоЗаказПокупателя._Marked AS ПометкаУдаления
INTO #ВТ_ЗАКАЗЫ
FROM
    _Document39 AS _ДемоЗаказПокупателя
WHERE
    _ДемоЗаказПокупателя._Posted = 0
-- ЗАПРОС ПАКЕТА 2. ВТ_ЗАКАЗЫ
SELECT 
    ВТ_ЗАКАЗЫ.Ссылка AS Ссылка
    , ВТ_ЗАКАЗЫ.Проведен AS Проведен
    , ВТ_ЗАКАЗЫ.ПометкаУдаления AS ПометкаУдаления
FROM
    #ВТ_ЗАКАЗЫ AS ВТ_ЗАКАЗЫ

SQL запрос на создание временной таблицы

-- ЗАПРОС ПАКЕТА 1. #ВТ_ЗАКАЗЫ
WITH #ВТ_ЗАКАЗЫ AS (SELECT 
    _ДемоЗаказПокупателя._IDRRef AS Ссылка
    , _ДемоЗаказПокупателя._Posted AS Проведен
    , _ДемоЗаказПокупателя._Marked AS ПометкаУдаления
FROM
    _Document39 AS _ДемоЗаказПокупателя
WHERE
    _ДемоЗаказПокупателя._Posted = 0)
-- ЗАПРОС ПАКЕТА 2. ВТ_ЗАКАЗЫ
SELECT 
    ВТ_ЗАКАЗЫ.Ссылка AS Ссылка
    , ВТ_ЗАКАЗЫ.Проведен AS Проведен
    , ВТ_ЗАКАЗЫ.ПометкаУдаления AS ПометкаУдаления
FROM
    #ВТ_ЗАКАЗЫ AS ВТ_ЗАКАЗЫ

SQL запрос использование временного запроса

В качестве источника можно указать объект с данными. Это делается по аналогии с работой модели запроса. В модели запроса допускается вместо имени таблицы передавать таблицу-объект типа Таблица значений или Данные формы коллекция. Выглядит это так: .Источник(Таблица-объект, Псевдоним). В этой модели в качестве источника можно также указать таблицу JSON.

Конструирование текста запроса из таблицы-объекта может пригодится для задач переноса данных между серверами, когда прямым запросом это сделать невозможно. Так можно получить результат запроса на одном сервере, прочитать его в текст запроса SQL, а затем уже выполнить на другом сервере. На 2-м сервере данные будут загружены из самого текста запроса.

Например сделаем запрос к результату из примера с пустым договором:

;//  ЗАПРОС ПАКЕТА. #ВТ_РЕЗУЛЬТАТ
МодельЗапроса.ЗапросПакета().Поместить("#ВТ_РЕЗУЛЬТАТ")
    .Выбрать()
        .Источник(Результат, "Результат")
        .Поле("Номер")
        .Поле("Дата")
        .Поле("Организация")
        .Поле("Контрагент")
        .Поле("Договор")
        .Поле("Проведен")
        .Поле("ПометкаУдаления")
;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
МодельЗапроса.ЗапросПакета("_ДемоЗаказПокупателя")
    .Выбрать()
        .Источник("#ВТ_РЕЗУЛЬТАТ")
        .Источник("Документ._ДемоЗаказПокупателя")
        .ВнутреннееСоединение("#ВТ_РЕЗУЛЬТАТ", "_ДемоЗаказПокупателя")
            .Связь("Номер, Дата")
        .Поле("_ДемоЗаказПокупателя.Ссылка")
;

Создание временной таблицы из результата выполнения предыдущего запроса SQL (в Конструкторе модели запроса SQL поддерживается использование предопределенной переменной Результат)

-- ЗАПРОС ПАКЕТА 1. #ВТ_РЕЗУЛЬТАТ
SELECT 
    Номер AS Номер
    , Дата AS Дата
    , Организация AS Организация
    , Контрагент AS Контрагент
    , Договор AS Договор
    , Проведен AS Проведен
    , ПометкаУдаления AS ПометкаУдаления
INTO #ВТ_РЕЗУЛЬТАТ
FROM
    (VALUES
        ('00-00000019', '4015-07-24 10:46:36', 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00, 0x00)
    ) AS Результат (Номер, Дата, Организация, Контрагент, Договор, Проведен, ПометкаУдаления)
-- ЗАПРОС ПАКЕТА 2. _ДемоЗаказПокупателя
SELECT 
    _ДемоЗаказПокупателя._IDRRef AS Ссылка
FROM
    #ВТ_РЕЗУЛЬТАТ AS #ВТ_РЕЗУЛЬТАТ
        INNER JOIN _Document39 AS _ДемоЗаказПокупателя
        ON #ВТ_РЕЗУЛЬТАТ.Номер = _ДемоЗаказПокупателя._Number AND #ВТ_РЕЗУЛЬТАТ.Дата = _ДемоЗаказПокупателя._Date_Time

Запрос SQL, где значения таблицы результата моделируются в строках VALUES

{
 "Колонки": [
  {
   "Имя": "Ссылка",
   "ТипЗначения": "СТРОКА(34)"
  }
 ],
 "Строки": [
  [
   "0xB1ACE0CB4ED5F65511E531D81C1C93F5"
  ]
 ]
}

Результат выполнения запроса из временной таблицы, сконструированной из строк VALUES в самом запросе. Запрос можно выполнить на другом сервере, отличным от того, в котором был получен первоначальный результат

Уничтожение таблицы

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

;//  ЗАПРОС ПАКЕТА. #ВТ_РЕЗУЛЬТАТ
МодельЗапроса.ЗапросПакета().Уничтожить("#ВТ_РЕЗУЛЬТАТ")
;

Уничтожение временной таблицы

-- ЗАПРОС ПАКЕТА 1. #ВТ_РЕЗУЛЬТАТ
DROP TABLE #ВТ_РЕЗУЛЬТАТ

SQL запрос уничтожение временной таблицы

Агрегатные функции

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

В полях и условиях модели можно использовать следующие агрегатные функции: SUM, COUNT, MIN, MAX, AVG. Использование таких функций автоматически добавляет в запрос группирующие поля. В список полей группировки входят все поля, которые не содержат агрегатную функцию.

;//  ЗАПРОС ПАКЕТА.
МодельЗапросаSQL.ЗапросПакета()
    .Выбрать()
        .Источник("Документ._ДемоЗаказПокупателя")
        .Источник("Справочник._ДемоКонтрагенты")
        .ВнутреннееСоединение("_ДемоЗаказПокупателя", "_ДемоКонтрагенты")
            .Связь("Контрагент = Ссылка")
        .Отбор(СтрШаблон("%1 = 0x01", МодельЗапросаSQL.ИмяПоляХранения("_ДемоЗаказПокупателя.Проведен")))
        .Отбор(СтрШаблон("COUNT(DISTINCT %1) > 1", МодельЗапросаSQL.ИмяПоляХранения("_ДемоЗаказПокупателя.Ссылка")))
        .Поле("_ДемоКонтрагенты.Наименование", "КонтрагентНаименование")
        .Поле(СтрШаблон("COUNT(DISTINCT %1)", МодельЗапросаSQL.ИмяПоляХранения("_ДемоЗаказПокупателя.Ссылка")), "Колво")
;

Использование агрегатных функций

-- ЗАПРОС ПАКЕТА 1.
SELECT 
    _ДемоКонтрагенты._Description AS КонтрагентНаименование
    , COUNT(DISTINCT _ДемоЗаказПокупателя._IDRRef) AS Колво
FROM
    _Document39 AS _ДемоЗаказПокупателя
        INNER JOIN _Reference15 AS _ДемоКонтрагенты
        ON _ДемоЗаказПокупателя._Fld2908RRef = _ДемоКонтрагенты._IDRRef
WHERE
    _ДемоЗаказПокупателя._Posted = 0x01
GROUP BY
    _ДемоКонтрагенты._Description
HAVING
    COUNT(DISTINCT _ДемоЗаказПокупателя._IDRRef) > 1

SQL запрос с агрегатными функциями в поле и в выражении отбора

{
 "Колонки": [
  {
   "Имя": "КонтрагентНаименование",
   "ТипЗначения": "СТРОКА(50)"
  },
  {
   "Имя": "Колво",
   "ТипЗначения": "ЧИСЛО(10)"
  }
 ],
 "Строки": [
  [
   "ООО \"Альфа\"",
   3
  ]
 ]
}

Результат выполнения запроса SQL с агрегатными функциями

Запросы на удаление и изменение

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

;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
МодельЗапроса.ЗапросПакета("_ДемоЗаказПокупателя")
    .Выбрать()
        .Источник("Документ._ДемоЗаказПокупателя")
        .Отбор(СтрШаблон("%1 = %2", МодельЗапроса.ИмяПоляХранения("_ДемоЗаказПокупателя.Договор"), МодельЗапроса.ИД()))
    .Удалить("_ДемоЗаказПокупателя")
;

Модель запроса SQL на удаление строк таблицы _ДемоЗаказПокупателя с пустым договором

-- ЗАПРОС ПАКЕТА 1. _ДемоЗаказПокупателя
DELETE _ДемоЗаказПокупателя
FROM
    _Document39 AS _ДемоЗаказПокупателя
WHERE
    _ДемоЗаказПокупателя._Fld2909RRef = 0x00000000000000000000000000000000

SQL запрос на удаление строк

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

Будьте внимательны! Если не указать поля для изменения, то запрос будет отработан как запрос на удаление!

;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
МодельЗапроса.ЗапросПакета("_ДемоЗаказПокупателя")
    .Выбрать()
        .Источник("Документ._ДемоЗаказПокупателя")
        .Отбор(СтрШаблон("%1 = %2", МодельЗапроса.ИмяПоляХранения("_ДемоЗаказПокупателя.Договор"), МодельЗапроса.ИД()))
    .Изменить("_ДемоЗаказПокупателя")
         .Установить("ПометкаУдаления", "1")
;

Установка признака пометки удаления по заказам с пустым договором. Обратите внимание, что имя поля таблицы для изменения указывается без полного пути!

-- ЗАПРОС ПАКЕТА 1. _ДемоЗаказПокупателя
UPDATE _ДемоЗаказПокупателя
SET
	_Marked = 1
FROM
	_Document39 AS _ДемоЗаказПокупателя
WHERE
	_ДемоЗаказПокупателя._Fld2909RRef = 0x00000000000000000000000000000000

SQL запрос на обновление таблицы _ДемоЗаказПокупателя

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

;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
МодельЗапроса.ЗапросПакета("_ДемоЗаказПокупателя")
    .Выбрать()
        .Источник("Документ._ДемоЗаказПокупателя")
        .Отбор(СтрШаблон("%1 = %2", МодельЗапроса.ИмяПоляХранения("_ДемоЗаказПокупателя.Договор"), МодельЗапроса.ИД()))
    .Изменить("_ДемоЗаказПокупателя")
         .Установить("ПометкаУдаления", СтрШаблон("CASE WHEN %1 = 0 THEN 1 ELSE 0 END", МодельЗапроса.ИмяПоляХранения("_ДемоЗаказПокупателя.Проведен")))
;

Модель запроса на изменение. Выражение значения получается путем разименования полей запроса в поля хранения

-- ЗАПРОС ПАКЕТА 1. _ДемоЗаказПокупателя
UPDATE _ДемоЗаказПокупателя
SET
    _Marked = CASE WHEN _ДемоЗаказПокупателя._Posted = 0 THEN 1 ELSE 0 END
FROM
    _Document39 AS _ДемоЗаказПокупателя
WHERE
    _ДемоЗаказПокупателя._Fld2909RRef = 0x00000000000000000000000000000000

SQL Запрос на установку значения с использованием логического выражения

Модель запроса SQL доступна только на сервере, однако полученный запрос SQL из модели можно выполнять в разных контекстах.

Модель может возвращать текст запроса в разных вариантах:

  • ПолучитьТекстЗапроса() - последний запрос пакета,
  • ПолучитьТекстЗапросаПакета() - полный текст запроса пакета,
  • ПолучитьПакетЗапросов() - массив запросов пакета, где элемент массива - структура вида {Имя, ТекстЗапроса}.

Полученный из модели текст запроса SQL уже можно вернуть в контекст клиента или продолжить использовать на сервере. Пример работы в режиме выполнения запроса на клиенте приложен в демо обработке "Демо Модель запроса SQL".

Основное назначение конструктора - получить текст запроса из готовой модели запроса и проанализировать его выполнение. Если запрос выполняется, значит нет синтаксических ошибок. Также это удобно для исследования работы запроса по модели. Это удобно для отладки запроса SQL.

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

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

 

Внешний вид обработки "Конструктор модели запроса SQL"

 

Демо пример сценария использования модели запроса SQL

 

Обработка с демо примером

 

В представленном демо-примере демонстрируется следующий сценарий использования модели. Вначеле выполняется запрос на чтение данных, затем результат переиспользуется во 2-м запросе для изменения.

В обработке есть две команды: первая выполняет обработку по сценарию, а вторая возвращает данные к исходному состоянию.

Обработка заключается в получении списка заказов, где незаполнен договор и нет пометки удаления, через соединение 1. Результат выполнения (список заказов) передается во второе соединение 2 и по сопоставленным заказам выполняется запись пометки удаления. Отмена изменений заключается в снятии пометки удаления по заказам с незаполненным договором. В обработке используется три запроса: получение непомеченных заказов с пустым договором, изменяющий запрос установки пометки на удаление и изменяющий запрос снятия пометки на удаление.

&НаСервере
Функция ТекстЗапросаНеПомеченныеЗаказыСПустымДоговором(ПараметрыСоединения)
    МодельЗапросаSQL = Общий.МодельЗапросаSQL();
    МодельЗапросаSQL
        .Схема1С(ПараметрыСоединения.Схема1С)
        .Схема(ПараметрыСоединения.Схема)
    ;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
    МодельЗапросаSQL.ЗапросПакета("_ДемоЗаказПокупателя")
        .Выбрать()
	        .Источник("Документ._ДемоЗаказПокупателя")
	        .Поле("_ДемоЗаказПокупателя.Номер")
	        .Поле("_ДемоЗаказПокупателя.Дата")
	        .Поле("_ДемоЗаказПокупателя.Организация")
	        .Поле("_ДемоЗаказПокупателя.Контрагент")
	        .Поле("_ДемоЗаказПокупателя.Договор")
	        .Поле("_ДемоЗаказПокупателя.Проведен")
	        .Поле("_ДемоЗаказПокупателя.ПометкаУдаления")
	        .Отбор(СтрШаблон("%1 = %2", МодельЗапросаSQL.ИмяПоляХранения("_ДемоЗаказПокупателя.Договор"), МодельЗапросаSQL.ИД()))
            .Отбор(СтрШаблон("%1 = 0x00", МодельЗапросаSQL.ИмяПоляХранения("_ДемоЗаказПокупателя.ПометкаУдаления")))
	;
    ТекстЗапроса = МодельЗапросаSQL.ПолучитьТекстЗапроса();
    Возврат ТекстЗапроса;
КонецФункции

Получение запроса из модели. Непомеченные заказы с пустым договором

&НаСервере
Функция ТекстЗапросаПометитьНаУдалениеЗаказыИзРезультата(ПараметрыСоединения, Таблица)
    МодельЗапросаSQL = Общий.МодельЗапросаSQL();
    МодельЗапросаSQL
        .Схема1С(ПараметрыСоединения.Схема1С)
    ;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
    МодельЗапросаSQL.ЗапросПакета("_ДемоЗаказПокупателя").Поместить("#ТАБЛИЦА")
	    .Выбрать()
	        .Источник(Таблица, "Результат")
	        .Поле("Номер")
	        .Поле("Дата")
	        .Поле("Организация")
	        .Поле("Контрагент")
	        .Поле("Договор")
	        .Поле("Проведен")
	        .Поле("ПометкаУдаления")
    ;
    МодельЗапросаSQL.ЗапросПакета()
        .Выбрать().Различные()
            .Источник("#ТАБЛИЦА")
            .Источник("Документ._ДемоЗаказПокупателя")
            .ВнутреннееСоединение("#ТАБЛИЦА", "_ДемоЗаказПокупателя")
                .Связь("Номер = Номер")
                .УсловиеСвязи(СтрШаблон("%1 = 0x00", МодельЗапросаSQL.ИмяПоляХранения("_ДемоЗаказПокупателя.ПометкаУдаления")))
        .Изменить("_ДемоЗаказПокупателя")
            .Установить("ПометкаУдаления", "0x01")
    ;
    ТекстЗапроса = МодельЗапросаSQL.ПолучитьТекстЗапросаПакета(); 
    Возврат ТекстЗапроса;	
КонецФункции

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

&НаСервере
Функция ТекстЗапросаУбратьПометкуУдаленияСЗаказовСПустымДоговором(ПараметрыСоединения)
    МодельЗапросаSQL = Общий.МодельЗапросаSQL();
    МодельЗапросаSQL
        .Схема1С(ПараметрыСоединения.Схема1С)
        .Схема(ПараметрыСоединения.Схема)
    ;//  ЗАПРОС ПАКЕТА. _ДемоЗаказПокупателя
    МодельЗапросаSQL.ЗапросПакета("_ДемоЗаказПокупателя")
        .Выбрать()
            .Источник("Документ._ДемоЗаказПокупателя")
            .Отбор(СтрШаблон("%1 = %2", МодельЗапросаSQL.ИмяПоляХранения("_ДемоЗаказПокупателя.Договор"), МодельЗапросаSQL.ИД()))
            .Отбор(СтрШаблон("%1 = 0x01", МодельЗапросаSQL.ИмяПоляХранения("_ДемоЗаказПокупателя.ПометкаУдаления")))
        .Изменить("_ДемоЗаказПокупателя")
            .Установить("ПометкаУдаления", "0x00")
    ;
    ТекстЗапроса = МодельЗапросаSQL.ПолучитьТекстЗапроса();
    Возврат ТекстЗапроса;
КонецФункции

Получение изменяющего запроса из модели. Сброс пометки удаления по заказам с пустым договором

Использование соединений 1, 2 демонстрирует возможность переноса данных между различными серверами через промежуточный результат запроса.

 
 Модуль команды обработки
 
 Модуль команды отмены

Поставка

Разработка проекта ведется в EDT с использованием платформы 8.3.21. При объединении с конфигурацией сбросьте признак "Объединять свойства конфигурации". Для варианта с расширением установите режим совместимости согласно версии вашей платформы.

Состав:

Конфигурация или расширение

Общие модули: Общий, ОбщийКлиент, ОбщийКлиентСервер, РаботаС_ADODB

Обработка: МодельЗапросаSQL, КонструкторМоделиЗапросаSQL

Подсистемы МПодсистемы.МодельЗапросаSQL

Зависимости

АТДМассив

Текущие ограничения Не поддерживаются вложенные запросы

 

Проект выложен на github.

Обновление от 29.06.2023

Добавлена поддержка объединений и параметров запроса по аналогии как в модели запроса 1С.

Теперь в запросе можно использовать несколько операторов Выбрать, Объединить/ОбъединитьВсе.

Можно использовать параметры в тексте запроса. В самом тексте параметр указывается с префиксом @, установка параметров через оператор Параметр(ИмяПараметра, Значение).

Модель DSL:

МодельЗапросаSQL
    .Параметр("ActID", "d5ae0dea-7bc8-4e9a-833a-3f45e8b7d45f")
;

Текст запроса:

-- ПАРАМЕТРЫ
DECLARE @ActID nvarchar(36) = N'd5ae0dea-7bc8-4e9a-833a-3f45e8b7d45f'

Обновление от 23.08.2023

Добавлена поддержка виртуальной таблицы остатков. Поля ресурсов нужно использовать без окончания Остаток.

Модель DSL:

;//  ЗАПРОС ПАКЕТА. ОстаткиТоваров
МодельЗапроса.ЗапросПакета("ОстаткиТоваров")
    .Выбрать()
        .Источник("РегистрНакопления._ДемоОстаткиТоваровВМестахХранения.Остатки", "ОстаткиТоваров")
        .Поле("ОстаткиТоваров.КоличествоОстаток")
        .Поле("ОстаткиТоваров.Номенклатура")
        .Поле("ОстаткиТоваров.МестоХранения")
        .Поле("ОстаткиТоваров.Организация")
        .Поле("ОстаткиТоваров.Количество", "КоличествоОстаток")
;//  Обработка результата
//МодельЗапроса.ВыполнитьЗапрос();
//Результат = МодельЗапроса.Результат("ОстаткиТоваров");

Запрос SQL:

-- ЗАПРОС ПАКЕТА 1. ОстаткиТоваров
SELECT 
    ОстаткиТоваров.КоличествоОстаток AS КоличествоОстаток
    , ОстаткиТоваров._Fld508RRef AS Номенклатура
    , ОстаткиТоваров._Fld507RRef AS МестоХранения
    , ОстаткиТоваров._Fld506RRef AS Организация
    , ОстаткиТоваров._Fld509 AS КоличествоОстаток
FROM
    _AccumRgT510 AS ОстаткиТоваров

 

Запрос SQL модель запроса

См. также

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

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

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

10000 руб.

02.09.2020    127233    689    389    

740

Infostart PrintWizard - создание и редактирование печатных форм в 1С 8.3

Пакетная печать Печатные формы Инструментарий разработчика Платформа 1С v8.3 Запросы 1С:Зарплата и кадры бюджетного учреждения 1С:Конвертация данных 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Платные (руб)

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

18000 руб.

06.10.2023    8431    25    6    

46

Infostart УДиФ: Управление данными и формами 1С

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

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

10000 руб.

10.11.2023    4755    12    2    

38

SALE! %

PowerTools

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

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

3600 2280 руб.

14.01.2013    178960    1085    0    

863

Бустер Конвертации данных 3 (Infostart Toolkit)

Инструментарий разработчика 8.3.14 1С:Конвертация данных Россия Платные (руб)

Расширение для конфигурации “Конвертация данных 3”. Добавляет подсветку синтаксиса, детальную контекстную подсказку, глобальный поиск по коду.

15000 руб.

07.10.2021    15123    3    12    

38

Многопоточность. Универсальный «Менеджер потоков» 2.1

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

Восстановление партий или взаиморасчетов, расчет зарплаты, пакетное формирование документов или отчетов - теперь все это стало доступнее. * Есть желание повысить скорость работы медленных алгоритмов! Но... * Нет времени думать о реализации многопоточности? * о запуске и остановке потоков? * о поддержании потоков в рабочем состоянии? * о передаче данных в потоки и как получить ответ из потока? * об организации последовательности? Тогда ЭТО - то что надо!!!

5000 руб.

07.02.2018    99900    240    97    

298

1С HTML Шаблоны / HTML Templates

Инструментарий разработчика Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

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

2040 руб.

27.12.2017    28434    4    10    

16

[ЕХТ] Фреймворк для Расширений 1С

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

"Фреймворк для Расширений 1С" это универсальное и многофункциональное решение, упрощающее разработку и поддержку создаваемых Расширений. Поставляется в виде комплекта из нескольких Расширений с открытым исходным кодом. Работает в любых Конфигурациях в режиме Управляемого приложения с режимом совместимости 8.3.12 и выше без необходимости внесения изменений в Конфигурацию.

3000 руб.

27.08.2019    18528    6    8    

40
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. sandr13 34 23.06.23 16:06 Сейчас в теме
Что-то мне подсказывает, что модуль для ускорения надо на c++ писать, ну или ещё лучше на ассемблере...
2. tormozit 7146 10.07.23 08:49 Сейчас в теме
Еще можно написать запрос 1С "ВЫБРАТЬ ..." и затем поймать выполненный из него запрос БД и из него относительно легко и достаточно универсально сделать нужный запрос БД. Пример есть в ИР https://www.hostedredmine.com/issues/956405
3. kalyaka 1071 23.08.23 21:21 Сейчас в теме
(2) эта разработка не является прямым конкурентом существующим инструментам преобразования запросов 1С в SQL.

Цель была в создании именно DSL в рамках встроенного языка 1С, на котором можно писать прямые SQL запросы. В отличии от инструментов результат будет всегда соответствовать текущей базе данных. Т.е. если написать запрос к таблице Справочник.Контрагенты и выполнить его в одной базе, то и в другой базе с другим возможным представлением внутренних имен таблицы и ее полей результат будет тот же. Это удобно, напромер, когда обработка пишется на тестовой базе, а затем используется на проде в базах клиентов.

Аналогично можно использовать конструктор модели как консоль, где результат не будет зависить от внутреннего представления и это тоже удобно.

Удобно также, что в одном запросе можно совмещать таблицы 1С и не 1С.
4. kalyaka 1071 23.08.23 21:31 Сейчас в теме
Еще модель запроса можно использовать как генератор запросов на SQL под разные базы
5. brr 183 14.09.23 18:19 Сейчас в теме
Круто! Писал похожее, на гитхабе валяется. Мне кажется для 1С запросов подобная модель бы тоже пригодилась.
6. kalyaka 1071 04.10.23 18:14 Сейчас в теме
8. brr 183 04.10.23 20:01 Сейчас в теме
7. kalyaka 1071 04.10.23 18:17 Сейчас в теме
даже в одной базе, как оказалось, внутренние имена таблиц могут меняться при работе с расширениями. Модель будет работать вне зависимости от этих изменений.
Оставьте свое сообщение