ВложеннаяТаблицаСхемыЗапроса

Типы · QuerySchemaNestedTable

Описывает вложенную таблицу схемы запроса.

Полное описание, параметры и ограничения

ВложеннаяТаблицаСхемыЗапроса (QuerySchemaNestedTable)

ВложеннаяТаблицаСхемыЗапроса (QuerySchemaNestedTable)

Доступен, начиная с версии 8.3.5.

Свойства:
Имя (Name)
Поля (Fields)

Описание:

Описывает вложенную таблицу схемы запроса.

Доступность:

Сервер, толстый клиент, внешнее соединение.

Использование в версии:

Доступен, начиная с версии 8.3.5.

Методическая информация

Практические примеры

Табличная часть в запросе: доступное описание, выбранные поля и вложенные колонки

Разбираем собственный список сборок с вложенными деталями. Отличаем описание доступных реквизитов от выбранной вложенной таблицы и её колонки; удваиваем выражение количества, проверяем весь запрос по независимому эталону и восстанавливаем его. Данные не читаются.

Где и как запускать

Полный серверный общий модуль УчебныеЗадачи своей новой конфигурации УчебныеВложенные85; в1С не запускался.

Подготовка

  1. Нужна НОВАЯ отдельная учебная база, не копия рабочей: платформа точно8.5.1.1343, имя конфигурации УчебныеВложенные85, совместимость Не использовать. Никаких расширений, фоновых заданий, подписок на события и иных бизнес-объектов. Все модули вручную пустые, кроме данного общего модуля. Здесь ничего в1С не запускается.

  2. Единственный справочник УчебныеСборки85: неиерархический, код Строка3, наименование40, без владельцев, реквизитов и предопределённых элементов. Единственная табличная часть Детали: два реквизита КодДетали Строка3 и Количество Число10,0. Не создавайте элементов и строк: нужен только собственный состав метаданных.

  3. Общий модуль УчебныеЗадачи: Сервер=Да, Вызов сервера=Да, Клиент=Нет, Глобальный=Нет, Привилегированный=Нет. Вставьте весь основной модуль. Своя внешняя обработка УчебныеВложения85 → управляемая Форма: команда/кнопка Выполнить с действием Выполнить; реквизиты не нужны. Полный отдельный модуль формы приведён ниже.

  4. Будущая ручная подготовка только вне опыта: завершить прежний свой сеанс, сохранить конфигурацию, Конфигурация → Обновить конфигурацию базы данных (F7), затем свежий собственный клиент и своя обработка. F7, клиент, BSL и контрольный опыт здесь не выполнялись.

Процедура ВыполнитьПример() Экспорт
    ПроверитьСвойПустойСтенд();
    ПроверитьСвоюМодельДеталей();
    ИсходныйТекст = "ВЫБРАТЬ Сборки.Код КАК Код,
    |Сборки.Детали.(КодДетали КАК КодДетали, Количество КАК Количество) КАК Детали
    |ИЗ Справочник.УчебныеСборки85 КАК Сборки";
    УдвоенныйТекст = "ВЫБРАТЬ Сборки.Код КАК Код,
    |Сборки.Детали.(КодДетали КАК КодДетали, Количество * 2 КАК Количество) КАК Детали
    |ИЗ Справочник.УчебныеСборки85 КАК Сборки";
    Схема = СоздатьСвоюВложеннуюСхему(ИсходныйТекст);
    ИсходныйЭталон = СоздатьСвоюВложеннуюСхему(ИсходныйТекст);
    УдвоенныйЭталон = СоздатьСвоюВложеннуюСхему(УдвоенныйТекст);
    СравнитьСвоиВложенныеСхемы(Схема, ИсходныйЭталон);
    ПроверитьСвойПовторныйРазборВложения(Схема, ИсходныйЭталон);
    Копия = СоздатьСвоюВложеннуюСхему(Схема.ПолучитьТекстЗапроса());
    Текущая = ПроверитьСвоюВложеннуюСтруктуру(Схема);
    Удвоенная = ПроверитьСвоюВложеннуюСтруктуру(УдвоенныйЭталон);
    Если Текущая.Поля.Получить(1) = Удвоенная.Поля.Получить(1) Тогда
        ВызватьИсключение "Исходное и удвоенное полные выражения должны различаться";
    КонецЕсли;
    Текущая.Поля.Установить(1, Новый ВыражениеСхемыЗапроса(Строка(Удвоенная.Поля.Получить(1))));
    СравнитьСвоиВложенныеСхемы(Схема, УдвоенныйЭталон);
    ПроверитьСвойПовторныйРазборВложения(Схема, УдвоенныйЭталон);
    СравнитьСвоиВложенныеСхемы(Копия, ИсходныйЭталон);
    Текущая = ПроверитьСвоюВложеннуюСтруктуру(Схема);
    Исходная = ПроверитьСвоюВложеннуюСтруктуру(ИсходныйЭталон);
    Текущая.Поля.Установить(1, Новый ВыражениеСхемыЗапроса(Строка(Исходная.Поля.Получить(1))));
    СравнитьСвоиВложенныеСхемы(Схема, ИсходныйЭталон);
    ПроверитьСвойПовторныйРазборВложения(Схема, ИсходныйЭталон);
    СравнитьСвоиВложенныеСхемы(Копия, ИсходныйЭталон);
    Сообщить("Верхние колонки: Код и Детали. Внутренние: КодДетали и Количество. Выражение количества восстановлено; копия не менялась");
КонецПроцедуры

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен свой новый стенд: единственный справочник сборок с собственной табличной частью";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьСвойТипВложенногоПоля(Описание, ОжидаемыйТип)
    Если ТипЗнч(Описание) <> Тип("ОписаниеТипов") Тогда
        ВызватьИсключение "Нужно описание полного типа своего поля";
    КонецЕсли;
    Типы = Описание.Типы();
    Если Типы.Количество() <> 1 Или Типы[0] <> ОжидаемыйТип Тогда
        ВызватьИсключение "Не совпал полный набор типов своего поля";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьСвоюМодельДеталей()
    Если ПривилегированныйРежим() Тогда
        ВызватьИсключение "Для собственного разбора не нужен привилегированный режим";
    КонецЕсли;
    МетаСборки = Метаданные.Справочники.Найти("УчебныеСборки85");
    Если МетаСборки = Неопределено Тогда
        ВызватьИсключение "Нужен свой справочник УчебныеСборки85";
    КонецЕсли;
    Если МетаСборки.Иерархический Или МетаСборки.ДлинаКода <> 3 Или МетаСборки.ДлинаНаименования <> 40
        Или МетаСборки.Реквизиты.Количество() <> 0 Или МетаСборки.ТабличныеЧасти.Количество() <> 1 Тогда
        ВызватьИсключение "Нужна только собственная согласованная модель сборок";
    КонецЕсли;
    МетаДетали = МетаСборки.ТабличныеЧасти.Найти("Детали");
    Если МетаДетали = Неопределено Тогда
        ВызватьИсключение "Нужна собственная табличная часть Детали";
    КонецЕсли;
    Если МетаДетали.Реквизиты.Количество() <> 2 Тогда
        ВызватьИсключение "В собственной табличной части ровно два реквизита";
    КонецЕсли;
    МетаКод = МетаДетали.Реквизиты.Найти("КодДетали");
    МетаКоличество = МетаДетали.Реквизиты.Найти("Количество");
    Если МетаКод = Неопределено Или МетаКоличество = Неопределено Тогда
        ВызватьИсключение "Нужны собственные КодДетали и Количество";
    КонецЕсли;
    ПроверитьСвойТипВложенногоПоля(МетаКод.Тип, Тип("Строка"));
    ПроверитьСвойТипВложенногоПоля(МетаКоличество.Тип, Тип("Число"));
    Если МетаКод.Тип.КвалификаторыСтроки.Длина <> 3
        Или МетаКоличество.Тип.КвалификаторыЧисла.Разрядность <> 10
        Или МетаКоличество.Тип.КвалификаторыЧисла.РазрядностьДробнойЧасти <> 0 Тогда
        ВызватьИсключение "Не совпали квалификаторы собственных реквизитов";
    КонецЕсли;
КонецПроцедуры

Функция СоздатьСвоюВложеннуюСхему(Текст)
    Схема = Новый СхемаЗапроса;
    Схема.РежимКомпоновкиДанных = Ложь;
    Схема.УстановитьТекстЗапроса(Текст);
    Возврат Схема;
КонецФункции

Процедура ПроверитьСвойКонецИмени(Имя, ОжидаемыйКонец)
    Если ТипЗнч(Имя) <> Тип("Строка") Тогда
        ВызватьИсключение "Нужно строковое имя собственного описания";
    КонецЕсли;
    Части = СтрРазделить(НРег(Имя), ".");
    Если Части.Количество() = 0 Или Части[Части.Количество() - 1] <> НРег(ОжидаемыйКонец) Тогда
        ВызватьИсключение "Не совпал собственный реквизит или имя табличной части";
    КонецЕсли;
КонецПроцедуры

Функция ПроверитьСвоюВложеннуюСтруктуру(Схема)
    Если Схема.РежимКомпоновкиДанных Или Схема.ПакетЗапросов.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен единственный собственный обычный запрос";
    КонецЕсли;
    Выбор = Схема.ПакетЗапросов.Получить(0);
    Если ТипЗнч(Выбор) <> Тип("ЗапросВыбораСхемыЗапроса") Или Выбор.Операторы.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен собственный запрос выбора с одним оператором";
    КонецЕсли;
    Оператор = Выбор.Операторы.Получить(0);
    Если ТипЗнч(Оператор) <> Тип("ОператорВыбратьСхемыЗапроса") Или Оператор.Источники.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен один собственный физический источник";
    КонецЕсли;
    Таблица = Оператор.Источники.Получить(0).Источник;
    Если ТипЗнч(Таблица) <> Тип("ТаблицаСхемыЗапроса")
        Или НРег(Таблица.ИмяТаблицы) <> НРег("Справочник.УчебныеСборки85") Или Таблица.Псевдоним <> "Сборки" Тогда
        ВызватьИсключение "Не совпал собственный справочник и его псевдоним";
    КонецЕсли;
    Доступная = Таблица.ДоступныеПоля.Найти("Детали");
    Если ТипЗнч(Доступная) <> Тип("ДоступнаяВложеннаяТаблицаСхемыЗапроса")
        Или ТипЗнч(Доступная.Поля) <> Тип("ДоступныеПоляСхемыЗапроса") Тогда
        ВызватьИсключение "Нужно настоящее описание доступной собственной табличной части";
    КонецЕсли;
    ПроверитьСвойКонецИмени(Доступная.Имя, "Детали");
    ДоступныйКод = Доступная.Поля.Найти("КодДетали");
    ДоступноеКоличество = Доступная.Поля.Найти("Количество");
    Если ТипЗнч(ДоступныйКод) <> Тип("ДоступноеПолеСхемыЗапроса")
        Или ТипЗнч(ДоступноеКоличество) <> Тип("ДоступноеПолеСхемыЗапроса") Тогда
        ВызватьИсключение "Нужны два реальных доступных реквизита собственной табличной части";
    КонецЕсли;
    ПроверитьСвойКонецИмени(ДоступныйКод.Имя, "КодДетали");
    ПроверитьСвойКонецИмени(ДоступноеКоличество.Имя, "Количество");
    ПроверитьСвойТипВложенногоПоля(ДоступныйКод.ТипЗначения, Тип("Строка"));
    ПроверитьСвойТипВложенногоПоля(ДоступноеКоличество.ТипЗначения, Тип("Число"));
    Если Оператор.ВыбираемыеПоля.Количество() <> 2 Или Выбор.Колонки.Количество() <> 2 Тогда
        ВызватьИсключение "Верхний уровень должен содержать код и одну вложенную таблицу";
    КонецЕсли;
    Код = Выбор.Колонки.Получить(0);
    Если ТипЗнч(Код) <> Тип("КолонкаСхемыЗапроса") Или Код.Псевдоним <> "Код" Или Код.Поля.Количество() <> 1 Тогда
        ВызватьИсключение "Первая верхняя колонка должна быть обычным кодом";
    КонецЕсли;
    Если ТипЗнч(Код.Поля.Получить(0)) <> Тип("ВыражениеСхемыЗапроса")
        Или Код.Поля.Получить(0) <> Новый ВыражениеСхемыЗапроса("Сборки.Код")
        Или Оператор.ВыбираемыеПоля.Получить(0) <> Код.Поля.Получить(0) Тогда
        ВызватьИсключение "Не совпало полное обычное выражение кода";
    КонецЕсли;
    ПроверитьСвойТипВложенногоПоля(Код.ТипЗначения, Тип("Строка"));
    Вложенная = Оператор.ВыбираемыеПоля.Получить(1);
    ВложеннаяКолонка = Выбор.Колонки.Получить(1);
    Если ТипЗнч(Вложенная) <> Тип("ВложеннаяТаблицаСхемыЗапроса")
        Или ТипЗнч(ВложеннаяКолонка) <> Тип("КолонкаВложеннаяТаблицаСхемыЗапроса") Тогда
        ВызватьИсключение "Вторые поле и колонка должны быть именно вложенной таблицей";
    КонецЕсли;
    ПроверитьСвойКонецИмени(Вложенная.Имя, "Детали");
    Если ТипЗнч(Вложенная.Поля) <> Тип("ПоляСхемыЗапроса")
        Или ТипЗнч(ВложеннаяКолонка.Колонки) <> Тип("КолонкиСхемыЗапроса")
        Или ТипЗнч(ВложеннаяКолонка.Поля) <> Тип("ПоляКолонкиСхемыЗапроса")
        Или ВложеннаяКолонка.Псевдоним <> "Детали" Или ВложеннаяКолонка.Поля.Количество() <> 1 Тогда
        ВызватьИсключение "Не совпали полные типы вложенных коллекций и внешний псевдоним";
    КонецЕсли;
    ИзКолонки = ВложеннаяКолонка.Поля.Получить(0);
    Если ТипЗнч(ИзКолонки) <> Тип("ВложеннаяТаблицаСхемыЗапроса") Тогда
        ВызватьИсключение "Поле вложенной колонки должно содержать настоящее вложенное описание";
    КонецЕсли;
    Если ИзКолонки.Имя <> Вложенная.Имя Или ИзКолонки.Поля.Количество() <> Вложенная.Поля.Количество() Тогда
        ВызватьИсключение "Выбранное вложенное поле и поле колонки должны описывать одну собственную таблицу";
    КонецЕсли;
    Если Вложенная.Поля.Количество() <> 2 Или ВложеннаяКолонка.Колонки.Количество() <> 2 Тогда
        ВызватьИсключение "Во вложенной таблице ровно две выбранные колонки";
    КонецЕсли;
    Имена = СтрРазделить("КодДетали,Количество", ",");
    Типы = СтрРазделить("Строка,Число", ",");
    Для Индекс = 0 По 1 Цикл
        Колонка = ВложеннаяКолонка.Колонки.Получить(Индекс);
        Если ТипЗнч(Колонка) <> Тип("КолонкаСхемыЗапроса") Или Колонка.Псевдоним <> Имена[Индекс]
            Или Колонка.Поля.Количество() <> 1 Тогда
            ВызватьИсключение "Не совпал порядок и псевдонимы всех внутренних колонок";
        КонецЕсли;
        Выражение = Вложенная.Поля.Получить(Индекс);
        Если ТипЗнч(Выражение) <> Тип("ВыражениеСхемыЗапроса")
            Или ТипЗнч(Колонка.Поля.Получить(0)) <> Тип("ВыражениеСхемыЗапроса")
            Или Выражение <> Колонка.Поля.Получить(0)
            Или Выражение <> ИзКолонки.Поля.Получить(Индекс) Тогда
            ВызватьИсключение "Внутренние поля и колонки должны содержать одинаковые полные выражения";
        КонецЕсли;
        ПроверитьСвойТипВложенногоПоля(Колонка.ТипЗначения, Тип(Типы[Индекс]));
    КонецЦикла;
    Возврат Вложенная;
КонецФункции

Процедура СравнитьСвоиВложенныеСхемы(Схема, Эталон)
    Факт = ПроверитьСвоюВложеннуюСтруктуру(Схема);
    Ожидание = ПроверитьСвоюВложеннуюСтруктуру(Эталон);
    Если Факт.Имя <> Ожидание.Имя Или Схема.ПолучитьТекстЗапроса() <> Эталон.ПолучитьТекстЗапроса() Тогда
        ВызватьИсключение "Не совпал полный собственный запрос с независимо разобранным эталоном";
    КонецЕсли;
    Для Индекс = 0 По 1 Цикл
        Если Факт.Поля.Получить(Индекс) <> Ожидание.Поля.Получить(Индекс) Тогда
            ВызватьИсключение "Не совпало полное выражение внутренней колонки";
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Процедура ПроверитьСвойПовторныйРазборВложения(Схема, Эталон)
    Повторная = СоздатьСвоюВложеннуюСхему(Схема.ПолучитьТекстЗапроса());
    СравнитьСвоиВложенныеСхемы(Повторная, Эталон);
КонецПроцедуры
УчебныеВложения85.Форма

Своя внешняя обработка УчебныеВложения85 → управляемая Форма → Модуль

Полный отдельный модуль собственной формы: модель запроса работает на сервере, здесь не запускалась.

&НаКлиенте
Процедура Выполнить(Команда)
    ВыполнитьНаСервере();
    Сообщить("Вложенная таблица: описание, колонки, удвоение выражения и восстановление проверены");
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
    УчебныеЗадачи.ВыполнитьПример();
КонецПроцедуры

Разбор по шагам

  1. Первый уровень запроса содержит Код и Детали; второй задаётся скобками после Сборки.Детали. Внутри явно выбраны КодДетали и Количество. Это вложенная таблица в поле выборки, а не отдельный источник Справочник.УчебныеСборки85.Детали.

  2. Сначала проверить собственную конфигурацию и полные типы метаданных. Из текущего физического источника получить доступную Детали через ДоступныеПоля.Найти. Проверить ДоступнаяВложеннаяТаблицаСхемыЗапроса, её строковое Имя и коллекцию доступных полей; найти оба собственных реквизита и проверить их полные наборы типов.

  3. Из ВыбираемыеПоля.Получить(1) получить ВложеннаяТаблицаСхемыЗапроса. Из верхних Колонки.Получить(1) получить КолонкаВложеннаяТаблицаСхемыЗапроса. Проверить все три разных коллекции: доступные поля, выбранные выражения ПоляСхемыЗапроса и поля колонки ПоляКолонкиСхемыЗапроса. Связь последней с текущей вложенной таблицей проверяется отдельно.

  4. У вложенной колонки внешний псевдоним Детали и ровно две внутренние обычные колонки: КодДетали Строка, Количество Число, порядок0/1. Проверяются все выражения полей и колонок, источник, верхний код и полные наборы типов, а не только размеры коллекций. Формат квалификации Имя не угадывается: проверяется конечное собственное имя, а затем полное имя и весь канонический текст сравниваются с самостоятельным эталоном.

  5. Независимо разобрать два явно написанных своих запроса: исходный и с Количество * 2. Взять полное выражение второй внутренней колонки удвоенного эталона, преобразовать документированным способом к строке и создать новое ВыражениеСхемыЗапроса. Передать его в текущая.Поля.Установить(1,...), не присваивать readonly имя или псевдоним вложенной колонки.

  6. Три полных контрольных разбора проверяют исходную схему, удвоенное выражение и восстановление. На каждом этапе сравнивается весь канонический текст с отдельным авторским эталоном и каждое внутреннее выражение. Исходная копия остаётся неизменной. После изменения дочерние описания получаются заново.

Как проверить результат

  1. Будущий результат модели: верхний уровень Код/Детали, внутренний КодДетали/Количество; меняется только формула количества на Количество * 2, потом возвращается исходная. Для воображаемой строки с количеством3 формулы означают3 и6, но ни такая строка, ни результат запроса здесь не создаются и не исполняются.

  2. Будущий отрицательный контроль: только в первом вызове Текущая.Поля.Установить заменить второй аргумент на Новый ВыражениеСхемыЗапроса("3"), оставив УдвоенныйТекст и эталон неизменными. Полное сравнение должно отказать при тех же именах, количестве колонок и типе Число. Вернуть код, сохранить/F7 вне опыта и открыть новый свой сеанс. Здесь контроль не выполнялся.

  3. runtimeVerifiedScenarios=0. Проверка справки и исходников не является запуском конструктора, выполнением запроса, проверкой формы или доказательством полученных данных.

Ожидаемый результат

Урок показывает три объекта одной табличной части и безопасное изменение именно её внутреннего выражения с полным восстановлением и независимой копией.

На что обратить внимание

  1. Все семь свойств трёх вложенных дескрипторов readonly. Полученную коллекцию выбранных полей можно менять документированным Установить, но свойство Поля, имя и псевдоним вложенной колонки не присваиваются. У обычной внутренней колонки другой контракт псевдонима.

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

  3. Доступные поля включают стандартные реквизиты табличной части: не утверждается, что их всего два. Ровно два — это явно выбранные внутренние поля, а не весь список доступных полей.

  4. ВыражениеСхемыЗапроса документированно поддерживает преобразование к строке и сравнение по строке. Относительные имена внутренних выражений не выдумываются: полное выражение берётся из отдельно разобранного своего текста.

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

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

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.