* Язык скриптов

Введение

Язык скриптов создан для того чтобы дать возможность разработчикам проектов самим писать программы и выполнить их из Домино.

Одно из прямых значений слова скрипт (script) – это ‘сценарий поведения’. В Домино нет необходимости описывать весь алгоритм работы программы на языке программирования. Стандартный алгоритм Домино подходит для подавляющего большинства разрабатываемых проектов. Различие между проектами заключается в поведении программы в некоторых ключевых местах. Проектировщик помещает в выбранное ключевое место свою процедуру (скрипт), тем самым изменяя стандартный алгоритм на требуемый сценарий.

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

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

Язык скриптов воплощает в себе идеи структурного программирования, модульности и наглядного изображения алгоритмов.

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

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

Основные конструкции языка

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

В программе существуют конструкции двух видов: данные и операции. Иначе их называют операнды (данные) и операторы (операции).

Данные – это та информация, которую обрабатывает компьютер. Операции – это как именно требуется обработать данные. Операции задают некоторые действия, выполнение которых компьютером приводит к изменению данных.

 

Основные конструкции языка

Основные конструкции языка

Данные

Принято различать два вида представления данных: константы и переменные.

Константа имеет постоянное значение, не изменяемое при выполнении программы.

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

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

Стандартные типы данных

На рисунке показаны описания стандартных типов данных в дереве проекта.

image-1648656895804.png

Описания всех типов данных расположены в проекте в библиотеке ‘Системная область’ в разделе ‘Классификация значений’. Стандартные типы находятся непосредственно в папке ‘Стандарты’. В остальных папках размещены производные типы. Для описания стандартного типа данных применяется элемент проекта с типом ‘Базовый класс значения’.

Основное преимущество чисел типа number – возможность явного указания десятичной точности результата при выполнении операций.  Это позволяет избежать проблемы накопления ошибок округления. Второе преимущество - большое количество значащих разрядов.

Остальные типы данных являются производными от этих стандартных.

Производные типы данных

В проекте описано множество производных типов данных, и этот список постоянно расширяется.

image-1648656914951.png

В папке ‘Объектные’ расположены производные типы, используемые для переменных, содержащих ссылки на объекты БД. Так тип ‘Объект’ может быть использован для любого из объектных типов. Если точно известен объект БД , то лучше применять типы Пользователь, Каталог, Партнер, Продукт, Документ, Строка, Проводка, Протокол, Контрольная точка. Элементы проекта, описывающие эти типы, ссылаются на соответствующие таблицы БД.

Для хранения списков объектов применяются типы, производные от стандартного типа UIDSET.

image-1648656931694.png

В папке ‘Системные’ находится описание типа данных ‘Код объекта БД’. Это строка длиной 20 символов. При описании параметров таблиц коды объектов имеют данный тип.

image-1648656947347.png

В папке ‘Проектные’ перечислены различные типы проектных элементов. Все они произведены от типа UID.

image-1648656963293.png

Папка ‘Данные’ содержит описания типов, с которыми работают внешние редакторы текстов (Word, Excel).

image-1648656978409.png

В папке ‘Числовые’ перечислены различные числовые типы. Типы различаются размером и точностью.

image-1648656993684.png

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

image-1648657012694.png

Типы ‘Дата+Время’ и ‘Дата’ отличаются лишь форматом отображения.

image-1648657027706.png

Папка ‘Счета’ содержит типы, выделенные из прочих проектных типов данных.

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

Значение NULL

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

NULL - специальное значение ‘Пусто’.

Свойства этого значения следующие:

Разработчики нередко используют NULL значение  в качестве результата выполнения функций.

В ДОМИНО понятие NULL значения привнесено из SQL. В SQL значение NULL означает отсутствие значения поля, и NULL-значение может размещаться в поле любого типа.

Преобразование типов данных

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

Правила преобразования типов следующие:

[число] операция [целое] ->> [число]

[целое] операция [число] ->> [целое]

 

Основные конструкции языка

Переменные

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

Глобальные переменные

Глобальный – общий, универсальный.

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

Область видимости глобальной переменной может быть специально ограничена настройщиком проекта.

Обычно глобальные переменные задаются либо в библиотеке ‘Системная область’, раздел ‘Параметры’, папка ‘Глобальные переменные’, либо в библиотеке ‘!Базовый набор’, раздел ‘Параметры’, папка ‘Глобальные переменные’.

image-1648658927312.png

Объяснение предназначения каждой из этих переменных не является целью данного руководства, поэтому лишь замечу, что элементы проекта, описывающие глобальные переменные имеют иконки разного цвета. Цвет иконки зависит от статуса проектного элемента. Если проектировщик присвоил глобальной переменной статус ‘Экспортный (Публичный’), то отображается иконка зеленого цвета. Для непубличных переменных используется иконка синего цвета.

image-1648658947679.png

На данном рисунке в списке глобальных переменных из библиотеки ‘!Базовый набор’ находится подстановка переменной ’Текущее ЦФО’. Определение глобальной переменной ’Текущее ЦФО’ находится выше – в библиотеке ‘Системная область’, что видно на предыдущем рисунке. Подстановку глобальной переменной применяют для назначения переменной начального значения.

Для глобальной переменной могут быть заданы следующие атрибуты:

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

Выражение рассчитывается после присваивания начального значения, указанного в предыдущем атрибуте, и после считывания значения из профиля. Т.е. если для глобальной переменной задан атрибут ‘Выражение’, то значение глобальной переменной при старте Домино всегда будет рассчитано как результат указанного выражения.

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

image-1648658969281.png

Другой пример использования глобальной переменной:

image-1648658984838.png

Функция для расчета курса получает дату из документа. UID требуемого документа считывается из глобальной переменной ‘Документ’.

 В следующем примере показано применение глобальной переменной в форме документа.

image-1648659002304.png

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

Контекстные переменные

Контекст (от лат. Contextus - тесная связь, соединение) –законченный в смысловом отношении отрывок текста, необходимый для определения смысла входящего в него слова или фразы.

Замысел появления контекста в Домино заключался в том, чтобы с помощью контекста точнее понимать смысл действий программы в отношении обрабатываемых данных. Иными словами, проектировщик, анализируя контекст, понимает какие именно объекты обрабатываются в рассматриваемом  месте программы. Для того чтобы контекстом было удобно пользоваться, контекст должен содержать как можно меньше частей. Этого можно добиться, если для каждого объекта завести свою переменную, в которую записывать UID текущей записи объекта.

Контекст в Домино – набор значений специальных (контекстных) переменных, содержащих идентификаторы текущих записей основных объектов БД.

Контекстные переменные перечислены в библиотеке ‘Системная область’, раздел ‘Параметры’, папка ‘Контекстные переменные’.

image-1648659021421.png

Список содержит контекстные переменные по всем объектам.

В папке ‘Прочие’ находятся дополнительные контекстные переменные. Дополнительные контекстные переменные были созданы до того, как в Домино появились локальные переменные и формальные параметры. В настоящее время имеются более удобные и понятные средства для реализации тех задач, в которых могут потребоваться эти переменные, поэтому использование дополнительных контекстных переменных не рекомендуется.

Для контекстной переменной могут быть заданы следующие атрибуты:

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

Контекстным переменным отводится следующая роль.

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

Рассмотрим подробнее механизм формирования контекста.

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

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

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

Пример использования контекстной переменной:

image-1648659040651.png

Обычно применяется следующая цепочка вызовов: вид просмотра документов –> форма документа –>  вид просмотра строк. При формировании заголовка  окна, содержащего вид просмотра строк, удобно использовать контекстную переменную <<Документ>>, поскольку эта переменная содержит UID именно того документа, строки которого отображаются.

Локальные переменные

Локальная переменная – переменная действующая только внутри процедуры, функции или выражения.

При описании процедуры (функции, выражения) можно указать необходимые локальные переменные в разделах ‘Локальные переменные’ или ‘Формальные параметры’. Здесь же задаются начальные значения переменных.

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

Пример описания локальных переменных для процедуры:

image-1648659062645.png

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

Если локальные переменные расположены в разделе ‘Формальные параметры’, то это означает, что процедура имеет соответствующие параметры для вызова.

Значения формальных параметров, указанные при вызове процедуры, имеют приоритет над начальными значениями в описании. Т.е. при старте процедуры в локальную переменную (являющуюся формальным параметром) будет записано значение при вызове, а если таковое отсутствует, то будет записано начальное значение из описания.

image-1648659078129.png

Функция ‘День’ возвращает номер дня недели. При вызове функции требуется указать значение формального параметра ‘Дата’.

image-1648659095108.png

При вызове функции 'День' формальный параметр ‘Дата’ заполняется датой документа.

 

Основные конструкции языка

Операции

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

В языке скриптов имеются операции всех перечисленных видов.

Оператор Присвоить

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

image-1648745571065.png

Разные варианты присваивания значений переменным (константы, результата выражения).

Операции, используемые  в выражениях

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

Подробнее о выражениях написано ниже.

Истинное и ложное значения операндов

Для логических операций имеются понятия истинного и ложного значений. Коротко истинное значение называют TRUE, а ложное – FALSE.

Считается, что числовой операнд имеет истинное значение, если число не равно ни 0, ни  NULL. Числовой операнд имеет ложное значение в противном случае (т.е. равен либо 0, либо NULL).

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

Операнд типа UID объекта имеет истинное значение, если UID не равен NULL. Операнд типа UID объекта имеет ложное значение, если UID равен NULL.

При написании выражений применяются следующие операции:

Если между строчными операндами не указать операцию, то программа выполнит такую запись как конкатенацию строк.

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

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

Условный оператор (Оператор IF)

‘Условный оператор’ позволяет указать, какую из двух ветвей программы выполнить в зависимости от значения (истинное или ложное) указанного условия.

Структура:

Условие - это переменная (выражение или функция), имеющая либо истинное, либо ложное значение.

THEN - последовательность операторов данного раздела выполняется если условие имеет истинное значение.

ELSE - последовательность операторов данного раздела выполняется если условие имеет ложное значение.

Обязательное наличие сразу обоих разделов THEN и ELSE не требуется.

Для разделов THEN и ELSE рекомендуется заполнять поле ‘Описание’, которое будет высвечено в качестве комментария к оператору IF.

Пример использования:

image-1648745631039.png

Если переменная ‘Устройство вывода отчетов’ имеет значение ‘В файл’, то выполняется группа операторов, расположенная в разделе THEN. В противном случае выполняются операторы раздела ELSE.

 Оператор выбора (Оператор CASE)

‘Оператор выбора’ позволяет указать, какую из нескольких ветвей программы выполнить в зависимости от значения указанного условия.

Структура:

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

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

ELSE - Если ни одно из значений ключа не совпало со значением условием, то выполняется последовательность операторов из данного раздела.

Не рекомендуется использовать оператор CASE вместо оператора IF. Данная конструкция удобна для сравнения условия с набором явно заданных констант, классификаторов и кодификаторов.

 Пример использования:

image-1648745686364.png

Функция ‘Месяц по дате’ возвращает название месяца. В условии оператора Выбора задан номер месяца. Значениями ключей являются числа от 1 до 12. Если номер месяца не совпадет ни с одним ключом (видимо на вход функции передана неверная дата), то функция возвращает значение NULL.

Оператор цикла (Оператор WHILE)

‘Оператор цикла’ обеспечивает многократное выполнение последовательности операторов до тех пор, пока выполняется указанное условие. Если условие имеет истинное значение, то последовательность операторов будет повторена. Как только условие примет ложное значение, то управление будет передано оператору, следующему за оператором цикла.

Циклом в языках программирования называют группу операторов, выполняемых многократно. Итерацией называют один проход через цикл.

Структура

Условие - это переменная (выражение или функция), имеющая либо истинное, либо ложное значение. Условие вычисляется в начале каждой итерации.

Блок действий – Последовательность операторов программы, выполняющаяся на каждой итерации цикла.

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

Пример использования:

image-1648745748911.png

Указанный цикл будет повторен i раз. Счетчик i уменьшается на 1 в начале каждой итерации.

Изменить порядок выполнения цикла можно с помощью операторов CONTINUE, BREAK, EXIT, RETURN.

image-1648745766459.png

Бесконечный цикл прерывается оператором BREAK.

 Оператор продолжить (Оператор CONTINUE)

‘Оператор продолжить’ изменяет последовательность выполнения операторов в зависимости от значения указанного условия. Если условие имеет ложное значение, то оператор CONTINUE не выполняет никаких действий. Если условие имеет истинное значение, то оператор выполняет действия в зависимости от места вызова:

В операторе CONTINUE  не обязательно указывать условие. Такая форма оператора называется безусловной. Безусловные операторы выполняются всегда.

Пример использования:

image-1648745784095.png

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

Оператор прервать (Оператор BREAK)

‘Оператор прервать’ изменяет последовательность выполнения операторов в зависимости от значения указанного условия. Если условие имеет ложное значение, то оператор BREAK не выполняет никаких действий. Если условие имеет истинное значение, то оператор выполняет действия в зависимости от места вызова:

В операторе BREAK  не обязательно указывать условие. Такая форма оператора называется безусловной. Безусловные операторы выполняются всегда.

Пример использования:

image-1648745801330.png

Если не удалось создать файл, то выполнение блока прерывается.

Оператор выхода (Оператор EXIT)

‘Оператор выхода’ прерывает последовательность выполнения операторов в зависимости от значения указанного условия. Если условие имеет ложное значение, то оператор EXIT не выполняет никаких действий. Если условие имеет истинное значение, то выполнение процедуры прерывается с командой возврата ’ошибка выполнения’.

В операторе EXIT  не обязательно указывать условие. Такая форма оператора называется безусловной. Безусловные операторы выполняются всегда.

Пример использования:

image-1648745818267.png

Если не удалось открыть файл, то выполнение процедуры прерывается.

Оператор возврата (Оператор RETURN)

‘Оператор возврата’ прерывает последовательность выполнения с командой возврата ’нормальное завершение’.

Если оператор RETURN используется внутри функции, то можно под оператором указать выражение. Значение указанного выражения функция вернет в качестве результата выполнения.

Пример использования в функции:

image-1648745840617.png

Функция возвращает строку, содержащую имя проектного элемента.

Если оператор RETURN используется внутри процедуры, то либо оператор записывается без возвращаемого результата, либо в нем явно указывается команда возврата.

Второй вариант применяется в процедурах, вызываемых из сценария вида просмотра.

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

image-1648745858931.png

Процедуры установки и отмены фильтров в виде просмотра возвращают команду возврата ‘Обновить содержимое экрана’.

Оператор Отложить выполнение

Оператор ‘Отложить выполнение’ применяется в видах просмотра при отборе данных.

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

Использование оператора ‘Отложить выполнение’ в других местах не рекомендуется и аналогично действию оператора RETURN.

Если условие имеет ложное значение, то оператор ‘Отложить выполнение’ не выполняет никаких действий. Если условие имеет истинное значение, то выполнение прерывается с командой возврата ‘нормальное завершение’.

В операторе ‘Отложить выполнение’  не обязательно указывать условие. Такая форма оператора называется безусловной. Безусловные операторы выполняются всегда.

Пример использования в виде просмотра:

image-1648745877691.png

При обычной схеме работы со списками данных применяются две компоненты программы. Источник данных (DATA SOURCE, DS) подготавливает записи, а интерфейс, в данном случае – это вид просмотра, отображает записи на экране. В приведенном примере DS считывает из базы данных записи документов. После считывания очередной записи управление передается интерфейсу (оператор ‘Отложить выполнение’). Интерфейс проверяет, заполнилось ли окно со списком записей. Если еще имеется место, то управление возвращается обратно в DS для получения очередной записи.

Применение оператора ‘Отложить выполнение’ позволяет пользователю начать работу с видом просмотра, не дожидаясь считывания всего списка из базы данных. Как только считано такое количество записей, которое достаточно для заполнения окна, так можно отображать окно на экране и позволить пользователю выполнять действия с записями. Если пользователю требуются другие записи, не поместившиеся на экране, то он сообщает об этом, нажимая соответствующие клавиши (стрелка вниз, следующая страница и т.д.). Интерфейс обрабатывает полученные команды и запрашивает у DS новые записи.

Оператор Вызова процедуры или функции

‘Оператор Вызова процедуры или функции’ запускает указанную процедуру.

Если с помощью данного оператора запускается функция, то возвращаемый функцией результат игнорируется.

Допускается рекурсивный вызов процедур, т.е. запущенная процедура может содержать вызов самой себя.

Если процедура или функция имеют формальные параметры, то необходимо указать значения этих параметров в папке ‘Значения параметров при вызове’.

Если запущенная процедура или функция завершили работу с командой возврата ’ошибка выполнения’, то соответствующее сообщение выдается в протокол.

Если для процедуры указан признак ‘Прервать при наличии ошибок’ и запущенная процедура (функция) завершилась с командой ошибки, то прерывается выполнение того блока, где данная процедура была вызвана. Это может быть либо основной блок ‘Выполнить действия’, либо блок ‘Всегда выполнять перед завершением’.

Пример вызова процедуры-метода с заполнением формальных параметров:

image-1648745894792.png

image-1648745909575.png

Это описание процедуры-метода.

Пример вызова функции  с заполнением формальных параметров.

image-1648745927642.png

image-1648745943220.png

Это описание функции.

Оператор Блок

‘Оператор Блок’ применяется для группировки последовательности операторов.

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

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

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

image-1648745960099.png

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

Оператор Выполнить блок

‘Оператор Выполнить блок’ запускает указанный блок действий. В операторе можно указать либо непосредственно блок действий, либо виртуальный блок действий.

Пример использования:

image-1648745977920.png

В описании функции имеется блок действий ‘Преобразование EAN13’. Этот блок вызывается на выполнение в основном блоке функции ‘Выполнить действия’.

 Оператор Завершить блок

‘Оператор Завершить блок’ прерывает выполнение указанного блока в зависимости от значения указанного условия. Если условие имеет ложное значение, то данный оператор не выполняет никаких действий. Если условие имеет истинное значение, то выполнение блока прерывается.

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

В операторе Завершить блок  не обязательно указывать условие. Такая форма оператора называется безусловной. Безусловные операторы выполняются всегда.

Если оператор Завершить блок применяется внутри блоков-событий в конструкциях вида ‘Отбор данных’, то данный оператор влияет только на текущий блок-событие. Текущий блок-событие прерывается. Оператор не влияет на вызов очередных блоков-событий, и отбор данных не прерывается.

Пример использования:

image-1648745995813.png

Оператор Завершить блок будет выполнен, если пользователь не  подтвердит удаление записи.

Выражения

Выражение является, наверное, самой применяемой конструкцией языка скриптов.

Выражения встречаются и в операторах присваивания, и в условиях выполнения условных и итеративных операторов, и внутри процедур и функций.

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

При описании выражения можно использовать следующие атрибуты:

image-1648746018463.png

image-1648746036352.png

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

 Пример использования:

image-1648746052519.png

Условный оператор (IF) - Позволяет указать, какую из двух ветвей программы выполнить в зависимости от значения (истинное или ложное) указанного условия.

image-1648746069489.png

Обязательное наличие сразу обоих разделов То и Иначе не требуется.

Пример использования:

image-1648746086130.png

Если между строчными операндами не указать операцию, то программа выполнит такую запись как конкатенацию строк.

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

Прочие атрибуты

 

Процедуры

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

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

Отличие процедур от процедур-методов заключается в команде возврата при возникновении ошибки в процессе выполнения. Если произошла ошибка, то процедура возвращает команду cmdCONTINUE, а процедура-метод – команду cmdRETURN_ CANCEL. Если выполнение завершилось без ошибок, то и обычная процедура, и процедура-метод возвращают команду cmdCONTINUE. Для процедур и процедур-методов есть также возможность явного задания команды возврата с помощью оператора RETURN. Подробнее о командах возврата написано ниже.

Процедуры различаются по способу создания. В одном случае процедура разрабатывается программистом на языке программирования (чаще всего на Visual С++) и подключается к Домино с помощью динамической библиотеки (файл с расширением dll). В проекте находится только описание этой процедуры. Атрибут ‘Точка входа’ в описании процедуры обязательно должен быть заполнен.

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

Для процедур поддерживается механизм наследования. Процедуры самого верхнего уровня являются базовыми. У базовых процедур имеются следующие атрибуты:

image-1648746924304.png

Примеры использования:

image-1648746970375.png

Сообщения об ошибках будут добавлены в файл export_news.log.

image-1648746986746.png

Протокол будет высвечен на экране.

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

image-1648747002863.png

Для создания процедуры на языке скриптов необходимо при заполнении поля класс указать {…скрипт-процедура…}.

image-1648747020693.png

image-1648747028732.png

Подробнее атрибуты процедур на языке скриптов рассмотрены ниже.

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

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

Во время активизации процедуры ей можно передать параметры. Параметры – это, по сути, начальные значения локальных переменных.

Параметры могут быть обязательные, необязательные и неявные.

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

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

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

 

Функции

Функция – это группа операторов, исполняемая как единое целое и предназначенная для выполнения некоторых действий и/или получения значения. Любую функцию можно вызвать как процедуру, проигнорировав возвращаемое ею значение.

Результат, возвращаемый функцией, можно использовать в выражениях, при заполнении параметров процедур и функций, в условных и итерационных операциях.

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

Функции, как и процедуры, различаются по способу создания. Если функция разработана программистом на языке Visual С++, то код функции записан в динамической библиотеке. В проекте находится только описание функции, причем атрибут ‘Точка входа’ содержит ссылку на динамическую библиотеку. Функции на языке скриптов целиком находятся в проекте.

Для функций поддерживается механизм наследования. Функции самого верхнего уровня являются базовыми. У базовых функций имеются следующие атрибуты:

image-1648749261155.png

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

image-1648749280160.png

Для создания функции на языке скриптов необходимо при заполнении поля класс указать {…скрипт-функция…}.

image-1648749296310.png

image-1648749303581.png

Подробнее атрибуты функций на языке скриптов рассмотрены ниже.

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

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

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

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

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

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

Функция называется контекстно-зависимой если функция имеет неявные параметры, и эти параметры являются контекстными переменными.

image-1648749323368.png

Функция ‘Курс РУБ (по контексту)’  имеет три неявных параметра: ’Дата документа’, ‘Валюта’, ‘Национальная валюта расчетов’. Два первых параметра являются контекстными переменными, а третий – глобальная переменная.

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

image-1648749341545.png

Примеры описания функций, работающих от текущего объекта.

image-1648749358504.png

image-1648749366208.png

 

Команды возврата

Основное предназначение команд в Домино 8 состоит в обеспечении взаимодействия источников данных и интерфейсов. С помощью команд источник данных сообщает интерфейсу что тот должен сделать. Подробнее об этом механизме написано в других книгах.

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

Все команды расположены в проекте по следующему адресу – библиотека 'Системная область’, раздел ‘Интерфейс’, раздел – ‘Команды’. При взаимодействии процедур используются только некоторые из этих команд.

При нормальном завершении процедуры выставляется команда возврата cmdCONTINUE.

Следующие команды возврата также считаются нормальным завершением.

Любая другая команда возврата (в том числе cmdRETURN_CANCEL и cmdEXIT) означает, что выполнение процедуры завершилось с ошибкой.

Команда ‘cmd RETURN_CANCEL’ предназначена для прерывания выполнения всей цепочки процедур, запускаемых во время акцепта (деакцепта, удаления) объекта.

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

Если функция внутри выражения завершилась с ошибкой, то вычисление выражения прерывается.

Для управления командой возврата применяются следующие операторы:

Если для процедуры или функции указан признак ‘Прервать при наличии ошибок’ и запущенная процедура (функция) завершилась с ошибкой, то прерывается выполнение того блока, где данная процедура была вызвана. Это может быть либо основной блок процедуры (‘Выполнить действия’), либо блок ‘Всегда выполнять перед завершением’. Сообщение об ошибке заносится в протокол.

 

Прочие операторы языка

Комментарий

Комментарий используется для документирования исходного кода и вставляется непосредственно в последовательность операторов.

Пример использования:

image-1648749726330.png

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

image-1648749742544.png

Выполнить от другого контекста

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

Объект - ссылка на выражение (переменную, функцию), которая рассчитывает UID обрабатываемого объекта.

Уточняющий параметр –для вызова процедуры или функции.

Пример использования:

image-1648749759335.png

Конструкция ‘Выполнить от другого контекста’ была применена для ввода проектного элемента ‘f(x) Документ прихода.Объект.Диалог редактирования’.
В сценарии вида просмотра продуктов имеется пункт для просмотра приходного документа.
Для корректного вызова функции ‘Объект.Диалог редактирования’ необходимо установить текущую запись документа. Для этого и применяется рассматриваемая конструкция, содержащая ссылку на локальную переменную ‘Документ прихода’. Ранее эта локальная переменная была заполнена UID-ом интересующего документа.

Управление индикатором

Конструкция Индикатор используется для отображения состояния процесса при длительной обработке данных. Результат вычисления выражения выводится в окне индикатора.

Пример использования:

image-1648749777777.png

Конструкция ‘Закрыть индикатор’ удаляет окно с ранее запущенным индикатором. Применение этой конструкции имеет смысл только в процедурах, высвечивающих  результат на экран. Конструкцию указывают для того, чтобы окно индикатора не мешало просмотру.

В любом случае при завершении процедуры все запущенные в ней индикаторы закрываются.

Пример использования:

image-1648749796189.png

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

Форма ввода

Данная конструкция предназначена для отображения формы ввода. Ссылка должна указывать на существующую в проекте форму.

Если ссылка указывает на базовую форму ‘ФОРМА ОТЧЕТА’, то можно описать новую форму. Для этого заполняется папка ‘Список полей формы’. В полях формы ввода можно использовать локальные, контекстные или глобальные переменные, которые получат свои значения после выполнения формы ввода.

При отказе пользователя от заполнения формы конструкция завершается с ошибкой. Можно изменить стандартный алгоритм работы, указав признак ‘При отказе от выбора не прерывать выполнение’.

Пример использования:

image-1648749814959.png

Вид просмотра

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

 

Структура процедуры (функции) на языке скриптов

Для описания процедуры (функции) на языке скриптов доступны следующие атрибуты:

image-1648749943856.png

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

Рассмотрим подробнее остальные атрибуты.

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

image-1648749964602.png

Чтобы процедура-наследник, в свою очередь,  могла управлять доступом своих наследников к вышеуказанным разделам и признакам  - в процедуре-родителе требуется установить признак ‘Допускает наследование атрибутов’. Наличие этого признака у процедуры-наследника определяется выбором этого признака в качестве наследуемого атрибута.

Локальные переменные

В этом разделе описываются локальные переменные процедуры или функции.

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

image-1648750003571.png

В описании  процедуры указаны три локальные переменные. Для переменной ‘Сумма скидки’ задано начальное значение в виде константы. Начальное значение для переменной ‘Торговое подразделение’ получается в результате расчета функции ‘Первое торговое подразделение’.

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

Ниже приводится пример рекурсивного вызова процедуры.

image-1648750019789.png

Процедура ‘Печать всех связанных документов’ просматривает связанные документы и выводит их UID-ы в log-файл. Документ считается связанным с текущим, если в поле ‘Родитель’ связанного документа записан UID текущего документа. Или такую связь можно назвать родитель-наследник. У наследника, в свою очередь, также могут быть связанные с ним документы. Процедура печатает наследников всех уровней от интересующего документа.

Разберем подробнее алгоритм процедуры.

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

Если процедуры связаны цепочкой наследования, то локальные переменные создаются одновременно для всей цепочки. Поэтому допустимо из процедуры-наследника обращаться к локальным переменным процедуры-родителя.

image-1648750037815.png

Первая процедура является базовой. Вторая процедура ссылается на базовую процедуру. В этой процедуре доступны как  локальные переменные, описанные в самой процедуре, так  и переменные из базовой процедуры. В третьей процедуре, поскольку она является наследником второй процедуры, можно использовать локальные переменные всех трех процедур. Переменная ‘Скидка’ описана в базовой процедуре. Описание переменной ‘Количество1’ находится во второй процедур, а переменная ‘Количество2’ указана как локальная для третьей процедуры.

Формальные параметры

В разделе ‘Формальные параметры’ располагаются описания параметров для вызова процедуры. По сути формальные параметры являются локальными переменными, и использовать их можно точно также, как и обычные локальные переменные. Отличие заключается в том, что начальное значение формальным параметрам можно задать двумя способами. В первом способе начальное значение указывается, как и для обычных локальных переменных, с помощью атрибута ‘начальное значение’. Во втором способе начальные значения формальных параметров задаются при вызове процедуры в разделе ‘Значения формальных параметров при вызове’.

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

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

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

Формальные параметры также применяют для передачи UID-ов объектов. В этом случае при вызове процедуры для получения нужного объекта указывают различные выражения. Тип формального параметра может быть либо ‘Объект’,  либо соответствовать типу объекта (‘Каталог’, ‘Продукт’, ‘Документ’ и т.д.).

image-1648750059446.png

Процедура имеет три формальных параметра типа ‘Объект’.

Для каждого формального параметра можно указать следующие атрибуты:

image-1648750076615.png

Таким образом, в языке скриптов реализована модель IN-OUT параметров (не путать с параметрами, передаваемыми по ссылке). Возврат значения в вызывающую процедуру происходит в момент выхода из вызываемой процедуры, но не в момент присвоения значения формальному параметру внутри вызываемой процедуры.

 Для лучшего понимания рассмотрим условный пример.

image-1648750092572.png

Функция ‘Наименование проектного элемента’ имеет два формальных параметра: ‘Проектный элемент’ и ‘Наименование проектного элемента’. Функция возвращает истинное значение, если удалось получить наименование элемента, или ложное значение, если переданный UID принадлежит не проектному элементу. Первый параметр используется для передачи значения в функцию, во втором параметре возвращается наименование. При вызове этой функции из основной процедуры заполняются оба параметра. Причем при заполнении второго параметра указана локальная переменная ‘Результат функции’. Значение в эту переменную записывается после выполнения функции  и  используется в дальнейшем тексте основной процедуры.

 Значения формальных параметров при вызове

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

image-1648750112716.png

Вызов процедуры с заполнением формальных параметров. Выражения ссылаются на проектные элементы. Описание процедуры находится на предыдущем рисунке.

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

Примеры:

image-1648750128121.png

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

image-1648750143318.png

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

Выполнить действия

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

image-1648750159882.png

Три процедуры связаны цепочкой наследования. В каждой процедуре заполняется переменная ‘Номер’. Затем значение этой переменной заносится в log-файл. Последовательность выполнения будет следующей: сначала выполнится ‘Наследник второго уровня’, затем - ‘Наследник первого уровня’, и наконец – ‘Базовая процедура’.

В log-файле последовательно будут записаны три числа: 3,2,1.

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

Для описания тела процедуры можно использовать следующие операторы языка скриптов:

image-1648750176895.png

Операторы ‘Присвоить’, ‘IF’, ’CASE’, ‘WHILE’, ‘CONTINUE’, ‘BREAK’, ‘EXIT’, ‘RETURN’, ‘ОТЛОЖИТЬ ВЫПОЛНЕНИЕ’, ‘ЗАВЕРШИТЬ БЛОК’, ‘ВЫПОЛНИТЬ БЛОК’, ‘БЛОК’, ‘Выполнить’ (Вызов процедуры или функции), ‘Выполнить от другого контекста’, ‘Комментарий’, Начало и конец многострочного комментария, ‘Индикатор’, ‘Закрыть индикатор’, ‘Форма ввода’, ‘Вид просмотра’ рассматривались ранее.

В дальнейшем тексте приведено подробное описание операторов как для работы с таблицами (‘Отбор данных’ в двух вариантах, ‘Изменить таблицу’, ‘Удалить из таблицы’, ‘Очистить таблицу’, Добавить в таблицу результаты запроса’, ‘Добавить в таблицу’), так и для обслуживания локальных таблиц (‘Отбор данных из локальной таблицы’, ‘Получить из локальной таблицы’, ‘Изменить локальную таблицу’, ‘Удалить из локальной таблицы’, ‘Очистить локальную таблицу’, ‘Добавить в локальную таблицу’).

Выполнить при завершении

Это блок операторов автоматически выполняется при завершении процедуры после основного блока. Блок ‘Выполнить при завершении’ запускается независимо от того,  как завершился основной блок – нормально или был прерван.

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

image-1648750197112.png

В цепочках наследования рекомендуется использовать раздел ‘Выполнить при завершении’ либо только у родителя, либо только у наследника. В противном случае понимание текста процедуры может быть затруднено.

Блоки действий

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

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

image-1648750220830.png

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

image-1648750237614.png

В процедуре-наследнике описаны еще несколько блоков действий. В основном блоке вызываются как блоки из базовой процедуры (‘…Инициализация’), так и блоки из процедуры-наследника (‘...Протоколируем начало приема’).

Виртуальные блоки

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

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

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

image-1648750255811.png

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

Подстановки виртуальных блоков

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

image-1648750272442.png

image-1648750280503.png

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

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

Кодификаторы

Кодификатор содержит список именованных проектных элементов. Обычно кодификатор применяется для выбора пользователем одной альтернативы из списка возможных вариантов.

image-1648750297076.png

Кодификатор содержит три элемента.

Для каждого элемента кодификатора можно указать имя и значение.

image-1648750315719.png

Локальные таблицы

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

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

image-1648750345960.png

image-1648750363826.png

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

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

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

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

image-1648750379722.png

Таблица содержит два поля типа ‘Объект’. Первое поле ссылается на локальную переменную ‘Старая базовая строка’. Второе поле ссылается на контекстную переменную ‘<<Строка>>’. Оба поля являются ключевыми. Записи таблицы будут отсортированы по возрастанию значения поля ‘Старая базовая строка’. Те записи, у которых значение этого поля совпадает, будут отсортированы по возрастанию значения поля ‘<<Строка>>’.

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

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

В примере на рисунке выше описан один блок ‘Базовая строка’. Внутри этого блока находится описание поля таблицы ‘Старая базовая строка’.

При отборе данных из локальной таблицы отслеживается изменение ключевых полей. Как только поменяется условие группировки блока (значения ключевых полей блока), программа для первой записи с новыми значениями ключевых полей генерирует событие   ‘Выполнить перед обработкой блока’, а после обработки последней записи с таким же значением ключа – событие ‘Выполнить после обработки блока’.

image-1648750399240.png

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

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

image-1648750416304.png

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

image-1648750432790.png

Локальная таблица содержит список банков. Записи в таблице не повторяются. Проверка на уникальность проводится по двум параметрам: ‘БИК’ и ‘Корр.счет’.

Наличие признака ‘внешняя’ для локальной таблицы не означает, что такая таблица будет видна во всех процедурах и функциях. Область видимости локальной таблицы рассчитывается по обычным для проекта Домино правилам. Локальная таблица доступна внутри той процедуры, где она была определена, и внутри процедур-наследников.

Далее рассмотрим операторы для работы с локальными таблицами:

image-1648750452861.png

Оператор Отбор данных из локальной таблицы

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

image-1648751280056.png

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

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

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

После завершения считывания записей из таблицы управление возвращается в процедуру.

Примеры.

image-1648750476107.png

Описание локальной таблицы.

image-1648750491640.png

Максимально возможное количество вызовов блоков-событий для данной таблицы.

 При отборе данных можно использовать операторы ‘CONTINUE’, ‘BREAK’ и ‘Завершить блок действий’.

Оператор ‘CONTINUE’ вызывает переход к получению следующей записи. Если оператор ‘CONTINUE’ вызвать из блока ‘Выполнить при старте’, то выборка данных прервется. Блок 'Выполнить при завершении’ в этом случае не вызывается.

image-1648750507277.png

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

Оператор ‘BREAK’ прерывает отбор данных. Блок ‘Выполнить при завершении’ не вызывается.

image-1648750523512.png

Если полученная строка не содержит новый товар, то считывание записей из таблицы прерывается. Блок ‘Выполнить при завершении’ отсутствует.

Оператор ‘Завершить блок действий’ завершает выполнение текущего блока-события.  Отбор данных не прерывается, и последовательность вызова очередных блоков-событий не меняется.

image-1648750539835.png

Если итоговая сумма по аналитике равна 0, то обработка текущего блока прерывается

При отборе данных из локальной таблицы изменение значений описанных в блоке ключевых полей определяет два события: вход и выход из блока. Последний уровень (поля вне блоков) попадает в событие ‘Выполнить после получения записи’, которое генерируется для каждой новой записи при отборе данных.

Оператор Получить из локальной таблицы

Оператор ‘Получить из локальной таблицы’ применяется для считывания записи из локальной таблицы. Для поиска записи используются текущие значения ключевых полей.

Если запись найдена, то заполняются все поля записи (точнее, заполняются значения всех не ключевых полей, а значения ключевых переменных не изменятся). Если запись не найдена, то значения всех не ключевых полей будут сброшены в NULL (пусто), а значения ключевых полей останутся без изменения.

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

image-1648750556006.png

Описание таблицы.

image-1648750573608.png

Перед вызовом оператора для получения записи из таблицы заполняются переменные ‘<<Продукт>>’ и ‘Запись обработана’.

Оператор ‘Получить из локальной таблицы’ допустимо вызывать из выборки данных по той же таблице, при этом указатель текущей записи выборки не сбивается.

Оператор Изменить локальную таблицу

Данный оператор изменяет текущую запись локальной таблицы. Оператор допустимо вызывать только если установлен указатель текущей записи. Указатель текущей записи устанавливается либо при отборе записей из этой таблицы, либо после вызова оператора ‘Получить из локальной таблицы’. Если указатель текущей записи не установлен, то никакие действия не выполняются.

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

image-1648750593360.png

Описание таблицы.

image-1648750609778.png

Перебираются записи из локальной таблицы. Перед изменением записи уменьшается значение поля ‘Количество’. В блоке ‘Выполнить после получения записи’ указатель текущей записи устанавливается автоматически.

С помощью оператора ‘Изменить локальную таблицу’ допустимо изменять записи в таблице, по которой идет выборка данных, при этом указатель текущей записи выборки не сбивается.

Оператор Удалить  из локальной таблицы

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

image-1648750626370.png

Описание таблицы.

image-1648750641260.png

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

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

Оператор Очистить локальную таблицу

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

image-1648750659639.png

Блок начинается с очистки локальной таблицы.

Оператор Добавить в локальную таблицу

Данный оператор добавляет запись в локальную таблицу. Значения полей записи берутся из переменных, которые были использованы при описании таблицы. При добавлении к таблице записи автоматически сортируются по ключу. Записи с одинаковым значением ключа записываются в хронологическом порядке. Если для таблицы указан признак ‘Исключать дублирующие записи‘, то попытка добавить запись с повторяющимся значением ключа отвергается. При этом выполнение процедуры не прерывается, и сообщение об ошибке не выдается.

image-1648750676862.png

Описание таблицы.

image-1648750694242.png

Перед вызовом оператора для добавления записи в таблицу заполняются переменные ‘Размер.Наименование’ и ‘Количество’.

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

Таблицы

Раздел ‘Таблицы’ содержит перечень используемых таблиц на сервере БД. В описании таблицы можно указать ее наименование на сервере, набор полей и набор индексов. При старте программы проверяется существование таблицы. Если таблица отсутствует, то программа создает таблицу в соответствии с описанием таблицы в проекте. Если таблица уже имеется, то программа проверяет описание всех полей таблицы. В случае расхождения описание поля в таблице сервера БД изменяется в соответствии с описанием в проекте.

При описании таблицы доступны следующие атрибуты:

image-1648751620426.png

image-1648751648232.png

Временная таблица ‘Остатки Товаров’ состоит из шести полей. Для таблицы указан индекс по базовому товару.

Таблицы могут быть описаны не только в разделе ‘Таблицы’ для процедур. В дереве проекта имеется специальный раздел для описания таблиц и запросов.

image-1648751665237.png

Библиотека ‘Новые примитивы почты’ содержит раздел ‘Структура базы данных’, в котором описаны таблицы для работы почтовой службы.

Основные таблицы БД описаны в библиотеке ‘Системная область’ в разделе ‘<<Объекты>>’. Их описание отличается от описания остальных таблиц.

image-1648751682941.png

Индексы основных таблиц БД описаны в библиотеке ‘Системная область’ в разделах, соответствующих объектам БД.

image-1648751697982.png

Раздел ‘Документ’ в папке ‘Индексы’ содержит список всех индексов по таблице ‘Документ’.

Запросы

В этом разделе описываются SQL запросы для выборки данных из таблиц БД. Описание запроса в ДОМИНО выполнено для стандарта SQL92. Для запросов можно применить механизмы наследования, запуск с параметрами, условия включения отдельных частей. Все это позволяет  выделить общую базовую часть для сложных и часто используемых запросов. При создании запроса можно ссылаться на базовые запросы и указывать нужные параметры, сортировки, условия отбора и т.д.

Процесс выполнения запроса можно разделить на два этапа. Первый этап называется  формированием (компиляцией) запроса. На этом этапе на основе описания запроса в проекте создается предложение на языке SQL. Второй этап заключается в выполнении запроса на сервере БД. Сформированное предложение передается серверу.

Запросы могут быть вложенными, т.е. их можно указывать не только в  разделе ‘Запросы’, но и внутри конструкций FROM, WHERE, IN, EXISTS, HAVING, в выражениях. При описании запроса можно сослаться на уже существующий запрос. В этом случае по правилам наследования становятся доступны атрибуты запроса-родителя.

Для описания запроса применяются следующие атрибуты:

image-1648751717596.png

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

Ключи оптимизации

Данный раздел содержит инструкции, позволяющие улучшить выполнение запроса.

image-1648751735157.png

Формальные параметры

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

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

image-1648751753330.png

Запрос имеет два формальных параметра: __ЦФО и __Подразделение.

Значения формальных параметров при вызове

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

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

image-1648751770715.png

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

From (Таблицы)

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

image-1648751787439.png

Можно указать одну или несколько таблиц.

Запрос выполняется по соединению таблиц.

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

image-1648751812802.png

Запрос выполняется по соединению двух копий таблицы ‘Продукт’.

Можно указать вложенный запрос или объединение нескольких вложенных запросов.

image-1648751830141.png

Запрос выполняется по результату вложенного  объединенного запроса.

Допустимы следующие условия объединения запросов:

image-1648751847783.png

Параметры

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

image-1648751864477.png

Базовый запрос в качестве результата вернет список значений следующих столбцов (перед наименованием столбца следует имя таблицы): ‘Партия.Поставщик’, ‘Продукт.Изготовитель’, ‘Группа.Справочник’, ‘Подгруппа.Справочник’, ‘Продукт.Продукт’, Партия.Продукт. Отдельно следует отметить, что запрос выполняется по трем таблицам БД: Обороты, Продукт и Каталог. Для соединения двух копий одной таблицы применяются синонимы. Для  таблицы ‘Продукт’ описаны синонимы ‘Продукт’ и ‘Партия’. Для таблицы ‘Каталог’ описаны синонимы ‘Группа’ и ‘Подгруппа’. Наличие элемента 'Использование (в режиме выполнения)' означает, что  в зависимости от описанного под этим элементом условия параметр может быть как включен в запрос, так и исключен из него.

image-1648751881840.png

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

 Выражения

Данный раздел содержит описания выражений, которые могут использоваться в различных частях запроса (его результате, разделе WHERE и т.д.).

Пример находится выше.

Where (Ограничения на отбор данных)

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

Для описания условия можно использовать следующие атрибуты:

image-1648751902654.png

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

Описание запроса (в том числе и условие) должно быть преобразовано в конструкцию на языке SQL (на этапе формирования запроса), которая будет передана серверу БД для выполнения.

При описании условий запроса надо четко разделять - какие из них будут выполняться на сервере БД, а какие выполнятся на рабочей станции в момент формирования запроса. Сервер БД ничего не знает о ДОМИНО и потому формальные параметры, переменные и функции ДОМИНО могут быть для SQL запроса только константами, значение которых вычисляется на момент формирования запроса. Для ссылки на них используются атрибуты, начинающиеся со слова Константа. Для ссылки на поля таблиц, функции SQL сервера и выражения запроса применяются атрибуты, начинающиеся со слова Результат.

image-1648751920152.png

Это условие из запроса-родителя

image-1648751934808.png

В запросе-наследнике к условию из запроса-родителя добавляется (операция И) еще одно условие.

 В ORACLE запись пустого UID-a выглядит вот так – HEXTORAW ('0000000000000000').

image-1648751954691.png

В запросе соединяются таблицы ‘Продукт’ и ‘Документ’.

Если атрибуты, начинающиеся со слова 'Константа', возвращают результат типа UIDSET (список уникальных идентификаторов), то на этапе формирования запроса условие преобразуется либо в предложение IN на языке SQL, либо в предложение ANY. Предложение IN будет применено в том случае, если данная константа входит в выражение с операциями равно и не равно. Для остальных операций сравнения (больше, меньше и т.п.) будет использовано предложение ANY.

Атрибуты для описания подзапроса внутри оператора EXISTS почти полностью совпадают с атрибутами запроса.

image-1648751975722.png

Рассмотрим пример использования оператора EXISTS.

image-1648751990865.png

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

Атрибуты для описания подзапроса внутри оператора IN почти полностью совпадают с атрибутами запроса.

image-1648752007029.png

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

Group By (Группировка)

В данном разделе описываются правила группировки записей для результата запроса. Наличие группировки позволяет применять к группам записей агрегатные функции сервера БД (COUNT, SUM, AVG, MAX, MIN).

image-1648752025695.png

Сначала записи будут сгруппированы по значению первого параметра. Внутри каждой из полученных групп записи будут сгруппированы по значению второго параметра. И так далее по всем указанным в разделе параметрам.

image-1648752041951.png

Каждая запись результата запроса содержит восемь полей (‘Партия’, ‘Продукт’, ‘Группа’, ‘Подразделение’, ‘Остаток’, три суммы). Записи будут сгруппированы сначала по значению поля ‘Партия’. Внутри полученных групп – по значению поля ‘Продукт’. Затем – по значению поля ‘Группа’. И последняя группировка – по значению поля ‘Подразделение’. В четырех выражениях вызывается функция агрегирования SUM, подсчитывающая арифметическую сумму значений указанных полей. Расчет будет выполнен для каждой группы записей.

При использовании группировки в результат запроса можно включать только поля группировки и результаты агрегирования. Все прочие поля в результате запроса перечислены быть не могут.

Having (Ограничения на группы строк заданных разделом Group By)

В данном разделе описывается условие, которое применяется к группам, заданным в разделе GROUP BY. Группы, для которых указанное условие не выполняется, исключаются из выходных данных. Условие HAVING действует на группы строк, в отличие от условия WHERE, которое действует на одну строку. При описании условия HAVING можно применять функции агрегирования.

Атрибуты для описания условие HAVING полностью совпадают с атрибутами для описания условия WHERE.

image-1648752063252.png

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

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

 Order By (Сортировка)

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

При описании сортировки применяются следующие атрибуты:

image-1648752083132.png

При отборе данных отслеживается изменение ключевых полей. Как только поменяется условие группировки блока (значения ключевых полей блока), программа для первой записи с новыми значениями ключевых полей генерирует событие   ‘Выполнить перед обработкой блока’, а после обработки последней записи с таким же значением ключа – событие ‘Выполнить после обработки блока’.

Самый нижний уровень группировки (поля вне блоков) попадает в одно событие 'Выполнить после получения записи', которое генерируется для каждой новой записи при отборе данных (после события ‘Выполнить перед обработкой блока’, но перед событием ‘Выполнить после обработки блока’).

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

image-1648752100543.png

Список документов сортируется по дате документа, внутри одинаковых дат – по UID-у документа.

image-1648752116223.png

Список документов со строками сортируется по дате документа, UID-у документа, UID-у строки. В запросе имеется обработка двух событий. Первое событие генерируется при изменении документа (дата и UID). Второе событие генерируется при отборе очередной записи.

Работа с таблицами БД

Соответствие SQL предложений конструкциям языка скриптов

Схематично команда SELECT в SQL выглядит следующим образом:

SELECT * | { [DISTINCT | ALL] <список полей> .,…}

            FROM {<имя таблицы> [<алиас>]}…     

                        [WHERE <условие>]

                        [GROUP BY {<имя столбца> <целое>} .,…]

                        [HAVING < условие >]

                        [ORDER BY {<имя столбца> | <целое>} .,…]

[{UNION [ALL]

SELECT * | { [DISTINCT | ALL] <список полей> .,…}

                        FROM {<имя таблицы> [<алиас>]}…     

                                   [WHERE < условие >]

                                   [GROUP BY {<имя столбца> <целое>} .,…]

                                   [HAVING < условие >]

                                   [ORDER BY {<имя столбца> | <целое>} .,…]

}]…;

Рассмотрим соответствие конструкций языка скриптов различным элементам команды и операторам SQL.

SQL предложение

Конструкция языка скриптов

SELECT в целом

Запрос в целом

DISTINCT

Признак ‘Distinct (Исключать дублирующие записи)’

ALL

По умолчанию

FROM {<имя таблицы> [<алиас>]}

Раздел ‘FROM (Таблицы)’

SELECT <список полей>

Разделы ‘Параметры’ и ‘Выражения’

[WHERE <условие>]

Раздел ‘WHERE (Ограничения на отбор данных)’

[GROUP BY {<имя столбца> <целое>} .,…]

Раздел ‘GROUP BY (Группировка)’

[HAVING < условие >]

Раздел ‘HAVING (Ограничения на группы строк заданных разделом GROUP BY)’

[ORDER BY {<имя столбца> | <целое>} .,…]

Раздел ‘ORDER BY (Сортировка)’

UNION [ALL]

Условия объединения запросов в разделе ‘FROM (Таблицы)’

Операторы сравнения и булевы операторы

Атрибуты разделов ‘WHERE’ и ‘HAVING’

IN

Для произвольного набора значений реализуется с помощью выражения.

Для результатов подзапроса - атрибут ‘IN (равно какому-либо из …) в разделах ‘WHERE’ и ‘HAVING’

BETWEEN

Реализуется с помощью выражения.

LIKE

Реализуется с помощью выражения и описанных в проекте функций SQL сервера.

IS NULL, NOT NULL

= NULL и <> NULL в выражениях.

Функции агрегирования: COUNT, SUM, AVG, MAX, MIN

Описанные в проекте агрегатные функции SQL сервера.

Соединение таблиц (join)

Внутреннее соединение реализуется через обычное равенство, а для внешнего соединения используется специальный атрибут ‘Результат (Внешнее соединение таблиц – допустимо отсутствие значения’

Алиасы

Реализуются автоматически, т.к. адресация к полям таблиц (подзапросов) осуществляется с помощью уточняющего параметра к ссылке на таблицу.

Вложенный запрос (подзапрос)

Атрибут ‘Запрос’ в разделах ‘WHERE’,  ‘HAVING’, ‘FROM (Таблицы)’

EXISTS

Атрибут ‘EXISTS (существует …) в разделах ‘WHERE’ и ‘HAVING’

ANY, ALL, SOME

Реализуется с помощью выражения.

Работа с таблицами БД

Для работы с таблицами БД применяется SQL ((Structured Query Language) - структурный язык запросов. С основами SQL можно ознакомиться в Приложении ‘SQL в Домино’.

Далее рассмотрим операторы для работы с таблицами:

image-1648793304449.png

Оператор Отбор данных

Оператор ‘Отбор данных’ применяется для последовательного считывания записей из основных таблиц БД с применением стандартных индексов. Стандартные индексы описаны в проекте особым образом.

Данная конструкция применяется редко, поскольку имеется более удобная конструкция ‘Отбор данных по запросу’ с дополнительными атрибутами.

Индексы основных таблиц БД формируются в момент создания БД. В проекте имеется лишь общее описание стандартных индексов - в библиотеке ‘Системная область’, раздел ‘Выборки’, папка ‘Стандарты’.

image-1648793321081.png

image-1648793352753.png

Стандартные индексы таблицы Пользователи.

Применение стандартных индексов предпочтительно по той причине, что отбор данных будет происходить максимально быстро.

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

image-1648793451193.png

Окно для выбора стандартного индекса.

После выбора стандартного индекса можно заполнить остальные атрибуты оператора:

image-1648793467617.png

image-1648793484536.png

Интересуют партнеры только класса ‘Подразделение’.

Ограничения по классам/типам – применяется для задания нескольких ограничений на классы и типы выбираемых записей. В остальном описание аналогично предыдущему атрибуту.

image-1648793498783.png

Интересуют партнеры только типов ‘Организация’ и ‘Юридическое лицо’.

Задание ограничений на класс и тип вынесены в отдельный атрибут поскольку поля ‘Класс’ и ‘Тип’ имеются во многих индексах. Учитывая эту особенность, программа пытается сконструировать более эффективный запрос к БД.

image-1648793515128.png

Для каждого поля можно указать следующие условия:

image-1648793529040.png

image-1648793544184.png

Интересуют наследники продукта, указанного в контекстной переменной <<Продукт>>.

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

Данные правила введены для удобства задания ограничений по дате.

image-1648793560466.png

Интересуют только неакцептованные документы.

image-1648793575110.png

Интересуют все документы за текущий день.

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

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

После завершения считывания записей из таблицы управление возвращается в процедуру.

Пример.

image-1648793590363.png

Для данной таблицы указано максимально возможное количество вызовов блоков-событий.

 При отборе данных можно использовать операторы ‘CONTINUE’, ‘BREAK’ и ‘Завершить блок действий’.

Оператор ‘CONTINUE’ вызывает переход к получению следующей записи. Если оператор ‘CONTINUE’ вызвать из блока ‘Выполнить при старте’, то выполнение этого блока прервется.

image-1648793605955.png

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

Оператор ‘BREAK’ прерывает отбор данных. Блок ‘Выполнить при завершении’ не вызывается.

image-1648793621626.png

Если для полученной строки  выполняется условие оператора BREAK, то считывание записей из таблицы прерывается. Блок ‘Выполнить при завершении’ отсутствует.

Оператор ‘Завершить блок действий’ завершает выполнение текущего блока-события.  Отбор данных не прерывается, и последовательность вызова очередных блоков-событий не меняется.

image-1648793637092.png

Если не разрешено создавать обратные проводки, то обработка текущего блока прерывается

Оператор Отбор данных (по запросу)

Оператор ‘Отбор данных (по запросу)’ применяется для последовательного считывания записей из основных таблиц БД по указанному запросу.

Можно описать новый запрос, можно сослаться на существующий запрос. Основные правила описания запросов были рассмотрены выше. Рассмотрим назначение остальных атрибутов.

image-1648793657091.png

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

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

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

После завершения считывания записей из таблицы управление возвращается в процедуру.

При отборе данных можно использовать операторы ‘CONTINUE’, ‘BREAK’ и ‘Завершить блок действий’. Действие данных операторов в  конструкции ‘Отбор данных (по запросу)’  аналогично их действию в конструкции ‘Отбор данных’.

Оператор Изменить таблицу

Данный оператор изменяет указанные записи таблицы.

При использовании оператора ‘Изменить таблицу’ необходимо указать либо одну из основных таблиц БД (в списке они расположены в папке <<Объекты>>), либо любую из  дополнительных таблиц.

image-1648793675135.png

Для оператора можно указать следующие атрибуты:

image-1648793697986.png

image-1648793713230.png

Из таблицы ‘Проводки’ отбираются все записи, связанные с интересующим документом (UID документа находится в контекстной переменной <<Документ>>).  Для каждой полученной строки очищается поле ‘Строка документа’.

Оператор Удалить  из таблицы

Данный оператор удаляет записи из таблицы.

При использовании оператора ‘Удалить из таблицы’ необходимо указать либо одну из основных таблиц БД (в списке они расположены в папке <<Объекты>>), либо любую из  дополнительных таблиц. Список доступных таблиц такой же, как и для оператора ‘Изменить таблицу’.

Для оператора можно указать следующие атрибуты:

image-1648793729475.png

image-1648793743901.png

image-1648793760032.png

Удаляются все строки документа, заданного в контекстной переменной <<Документ>>.

Оператор Очистить таблицу

Оператор ‘Очистить таблицу’ удаляет все записи из таблицы.

При использовании оператора ‘Очистить таблицу’ необходимо указать либо одну из основных таблиц БД (в списке они расположены в папке <<Объекты>>), либо любую из  дополнительных таблиц. Список доступных таблиц такой же, как и для оператора ‘Изменить таблицу’.

image-1648793775889.png

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

Оператор Добавить в таблицу

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

При использовании оператора ‘Добавить в таблицу’ необходимо указать либо одну из основных таблиц БД (в списке они расположены в папке <<Объекты>>), либо любую из  дополнительных таблиц. Список доступных таблиц такой же, как и для оператора ‘Изменить таблицу’.

Значения полей указываются в папке ‘Начальные значения полей объекта’.

image-1648793793840.png

Описание таблицы

image-1648793808077.png

Добавление новой записи в таблицу

Оператор Добавить в таблицу результаты запроса

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

Можно описать новый запрос, можно сослаться на существующий запрос. Основные правила описания запросов были рассмотрены выше. Рассмотрим назначение остальных атрибутов.

image-1648793824554.png

image-1648793850359.png

Описание таблицы

image-1648793863725.png

Результат запроса по таблице ‘Документ’  добавляется в таблицу ‘Для удаления’. Таблица ‘Для удаления’ содержит два столбца. Оба этих столбца заполняются из соответствующих параметров каждой отобранной записи таблицы ‘Документ’.

 

Виды просмотра

Для создания нового вида просмотра на языке скриптов необходимо при заполнении поля класс указать базовый вид просмотра ‘ПРОСМОТР СПИСКА ДАННЫХ’. Но совсем не обязательно каждый вид просмотра описывать с нуля. В разделе ‘ПРОСМОТР СПИСКА ДАННЫХ’, кроме базового вида просмотра, находятся базовые виды просмотра для работы с таблицами ДОМИНО, проектными элементами, элементами множества и т.д. При наследовании от них можно использовать их базовую логику, переопределяя лишь необходимое. Также многие из этих базовых видов просмотра имеют развитый набор формальных параметров.

image-1648802507223.png

image-1648802515058.png

Все элементы папки ‘ПРОСМОТР СПИСКА ДАННЫХ’ в конечном итоге имеют одного родителя – базовый ‘ПРОСМОТР СПИСКА ДАННЫХ’. Этот проектный элемент не только описывает базовые атрибуты вида просмотра, но и содержит ссылку на dll, где находится программная реализация вида просмотра.

image-1648802532965.png

В проекте также имеются виды просмотра, не являющиеся процедурами на языке скриптов. Эти виды просмотра появились задолго до возникновения в Домино языка скриптов, и поэтому их называют обычными видами просмотра. Описание обычных видов просмотра намного проще, но проектировщик имеет меньше возможностей для добавления специальных процедур, изменяющих стандартный алгоритм. Обычные виды просмотра имеют базового родителя – вид просмотра ‘ОБЪЕКТЫ’, который находится в библиотеке ‘Системная область’.

image-1648802551377.png

При описании вида просмотра доступны следующие атрибуты:

image-1648802569326.png

Далее следуют наследуемые атрибуты:

image-1648802586220.png

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

image-1648802604705.png

image-1648802622832.png

Кроме обычных для видов просмотра команд, часть которых зарезервирована и обрабатывается видом просмотра автоматически, а другая часть подразумевает вполне определенные действия, есть около двадцати специальных команд (формата USER XX …), использование и смысл которых определяется проектировщиком. Все действия по этим командам должны быть описаны в разделе ‘Обработка команд’. Например, вот так:

image-1648802641090.png

image-1648802659063.png

Описание выполняемых действий находится в разделе ‘Обработка команд’.

image-1648802675940.png

image-1648802695079.png

image-1648802712233.png

В разделе ‘Локальные переменные’ описано очень много переменных. Для вида просмотра требуются лишь некоторые из них. Раздел ‘Список переменных, сохраняемых в строке‘ содержит ссылки на переменные, которые необходимо записать в каждую строку вида просмотра независимо от того, участвуют ли данные переменные в операторах присваивания внутри раздела 'Отбор данных', или ссылается ли на какую-либо из них атрибут 'Идентификатор объекта'.

Например.

image-1648802728793.png

В строке вида просмотра будут записаны все переменные, участвующие в операторах присваивания внутри раздела 'Отбор данных', и переменная, на которую ссылается атрибут 'Идентификатор объекта', кроме переменных ‘Количество файлов’, ‘Количество узлов’ и ‘Суммарный размер’.

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

image-1648802749864.png

Атрибут ‘Заголовок’ содержит ссылку на переменную ‘Заголовок вида просмотра’. Этой переменной присваивается значение в рассматриваемом разделе.

image-1648802768143.png

Для вида просмотра описаны две локальные таблицы, содержащие проектные элементы. Для проверки наличия связанных данных из локальной таблицы ‘Типы объектов по родителю’ считывается элемент, соответствующий текущей строке вида просмотра.

image-1648802786045.png

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

image-1648802805241.png

В разделе перечислены команды, которые интерфейс может возвращать для данного вида просмотра. Для каждой команды описаны выполняемые действия.

Например, закрыть открытые в виде просмотра файлы.

image-1648802822175.png

Поля должны ссылаться на локальные переменные или формальные параметры вида просмотра, значения которых используются при создании строк вида просмотра в разделе 'Отбор данных'. (Раздел 'Отбор данных' выполняется каждый раз при установке и снятии фильтра.)

Например, список полей фильтра для вида просмотра, отображающего каталоги. Вид просмотра называется ‘КАТАЛОГИ'.

image-1648802839647.png

В описании поля ‘Родитель’ имеется ссылка на исходный вид просмотра.

Отбор данных для вида просмотра

Вид просмотра отображает список строк. Список формируется в разделе ‘Отбор данных’ с помощью функции ‘Список данных.Добавить запись’. По умолчанию, в строке вида просмотра сохраняются все переменные, которым присваивается значение в разделе 'Отбор данных', и переменная, на которую ссылается атрибут 'Идентификатор объекта'. Список переменных уточняется с помощью атрибутов ‘Список переменных, сохраняемых в строке’ и ‘Список переменных, не сохраняемых в строке’.

Рассмотрим два примера формирования списка строк для вида просмотра.

Формирование списка проектных элементов

image-1648802859830.png

Описание переменной для хранения UID-а колонки вида просмотра.

image-1648802875936.png

Используемый кодификатор.

image-1648802892207.png

Список для вида просмотра содержит четыре элемента из кодификатора.

Формирование списка из таблицы ДОМИНО

Отбор данных для вида просмотра Каталогов.

image-1648802918033.png

Выполняется запрос по таблице ‘КАТАЛОГИ’. Запрос возвращает все записи из таблицы. Записи  последовательно сохраняются в строках вида просмотра.

Для быстрого высвечивания первой страницы списка применяются атрибут ‘Быстрый показ первых записей’ и оператор ‘Отложить выполнение’.

Вид просмотра с дополнительной зоной

В видах просмотра (использующих стандартный табличный интерфейс ‘Просмотр (Browse)') можно открыть дополнительную зону.

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

Для того чтобы поле было высвечено в дополнительной зоне необходимо (в режиме выполнения при настройке колонок вида просмотра) указать для этого поля вид отображения ‘В форме’ (или ‘В колонке и форме’).

image-1648802937694.png

В дополнительной зоне появится закладка ‘Остальные поля’.

image-1648802956859.png

Название закладки ‘Остальные поля’ изменить нельзя.

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

image-1648802977276.png

Вид экрана в этом случае будет такой:

image-1648802995618.png

В качестве текста на закладке используется заголовок связанного вида просмотра, в данном случае это ‘СТРОКИ’.

Записи в связанном виде просмотра редактировать нельзя.

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

Эта возможность используется совместно с функциями сканирования документов в библиотеке работы с сертификатами.

image-1648803019020.png

 

* Отчёты

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

В общем случае, отчетом может быть любая скрипт–процедура.

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

image-1648803542830.png

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

image-1648803561017.png

Просмотр результата выполнения процедуры вывода в протокол.

Можно немного изменить процедуру и не отображать результат на экране, а записывать протокол в файл.

image-1648803592220.png

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

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

Результат отчета можно отобразить с помощью редактора обычных текстовых файлов, HTML броузера, редактора текстов Microsoft WinWord, редактора электронных таблиц  Microsoft  Excel. Все эти программы работают по сходному алгоритму. Программа получает файл и отображает его в форме, присущей именно этой программе. Форма отображения задается специальными инструкциями, расположенными в файле. Причем, каждая программа строго требует соблюдения определенного формата для обрабатываемых файлов.

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

Каждый шаблон имеет внутреннюю структуру. Эта структура отражается с помощью  блоков. Блок – это составная часть шаблона. Список блоков и последовательность их вызова однозначно определяют структуру шаблона.

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

Блоки применяются при отборе данных для отчета. Удобнее и быстрее отбирать данные порциями. Сначала подбираются все данные, которые будут напечатаны в первом блоке. Печатается первый блок. Затем, подбираются данные для второго блока. Печатается второй блок. И так далее. Если требуется напечатать блок несколько раз, то отбор данных и печать блока обычно проводится в цикле.

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

Рассмотрим пример отображения в текстовом формате (TEXT).

image-1648803616136.png

Результат выполнения скрипта-отчета.

{{ЗАГОЛОВОК}}

  Список пользователей на дату {ДАТА}

-----------------+----------------------+

       id        |     Наименование     ¦

-----------------+----------------------+

{{ПОЛЬЗОВАТЕЛЬ}}

[<Пользователь  ] [<Наименование       ]

{{ИТОГО}}

 ----------------------------------------

 Всего            {Всего}

Шаблон отчета. При печати полей указано выравнивание влево. Шаблон содержит три блока: ЗАГОЛОВОК, ПОЛЬЗОВАТЕЛЬ, ИТОГО. Блок ПОЛЬЗОВАТЕЛЬ печатается столько раз, сколько имеется записей пользователей. В данном шаблоне этот блок применен для заполнения таблицы.

image-1648803663363.png

Текст скрипта-отчета.

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

Посмотрим, как можно отобразить тот же текст в формате  HTML.

image-1648803682598.png

Пример печати списка пользователей в формате HTML

Текст HTML шаблона по сравнению в текстовым шаблоном выглядит сложнее.

{{ЗАГОЛОВОК}}

<html>

<head>

   <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">

   <link rel=stylesheet href="file:{STYLE}" type="text/css">

</head>

<body>

<H1> Список пользователей на дату {ДАТА} </H1>

<table class="MainTable" border="1" width="100%" cellspacing="0" cellpadding="4" align=center>

<tr class="TableHeader">

    <td> id </td>

    <td> Наименование </td>

</tr>

{{ПОЛЬЗОВАТЕЛЬ}}

<tr class="TableBody">

    <td align=left>{Пользователь}</td>

    <td align=left>{Наименование}</td>

</tr>

{{ИТОГО}}

</table>

<p>Всего: {Всего}

</body></html>

Структура шаблона (список блоков) осталась прежней, поскольку отбор данных не меняется.

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

Шаблоны в формате HTML имеют много возможностей по управлению изображением и достаточно просто описываются. Поэтому это самые распространенные шаблоны в проектах на ДОМИНО. Подробнее о том, какие бывают шаблоны и как они описываются, написано ниже.

Теперь перейдем к разбору текста отчета-скрипта из приведенного примера.

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

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

Схема выполнения отчета-скрипта для печати с шаблоном должна содержать следующую последовательность вызовов этих процедур:

Подробнее об этих процедурах написано ниже.

Для упрощения создания отчетов разработаны специальные базовые отчеты-скрипты, в которые вынесены инициализация, отображение и закрытие отчета. Там же определены виртуальные блоки, содержимое которых можно заполнить в отчетах-наследниках.

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

Посмотрим, как можно переписать пример печати справочника пользователей.

image-1648803744146.png

Вместо двух блоков ‘Выполнить действия’ и ‘Выполнить при завершении’ появляется постановка виртуального блока ‘Печать данных’. Внутри этого блока находятся вызовы процедуры ‘Отчет.Печать блока’. Изменилось описание шаблона. Теперь шаблон ссылается на базовый шаблон. В описании блоков шаблона используется наследование блоков из базового шаблона, но это делать не обязательно. Можно определить все блоки заново.

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

Рекомендуется при написании отчетов-скриптов ссылаться на базовые отчеты.

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

Атрибуты отчетов-скриптов

Для создания отчета на языке скриптов необходимо при заполнении поля класс указать любой из элементов папки {…скрипт-отчет…}.

image-1648803766113.png

image-1648803774411.png

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

Например.

image-1648803791265.png

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

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

При описании отчетов доступны следующие атрибуты:

image-1648803808530.png

Назначение большинства атрибутов скрипта-отчета совпадает с назначением соответствующих атрибутов обычной процедуры. Другая часть атрибутов присуща именно отчетам. Такие атрибуты рассмотрим подробнее.

image-1648803832420.png

Шаблоны отчетов

В шаблоне отчета описываются содержание и форма представления результата отчета.

Шаблон отчета состоит из текстовой части и атрибутов шаблона.

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

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

Для каждой из этих программ применяются собственные (отличные от других) элементы оформления. Кроме того, программа сможет корректно отобразить текст только в том случае, если текст сформирован по правилам (в формате), накладываемым этой программой. Редактор текстовых файлов отображает текстовые файлы. Для HTML броузера требуются тексты в формате HTML. WinWord и Excel работают только со ‘своими’ файлами.

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

Внешне файлы разного формата различаются расширениями.

Шаблоны форматов TEXT и HTML могут быть созданы непосредственно в проекте. Файлы с шаблонами для WinWord подключаются с помощью атрибута ‘Внешний файл шаблона’.

В текстовую часть шаблона также включаются специальные элементы для ДОМИНО. Эти элементы выделяют месторасположение данных внутри обрамляющего текста. Выделяются поля и блоки. На место полей шаблона будут подставлены данные. Блоки необходимы потому, что являются минимальной единицей печати. Блок может быть напечатан только целиком.

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

В том случае, когда отчеты связаны цепочкой наследования, то шаблон отчета-ребенка может ссылаться на шаблон отчета-родителя. При этом, если отчет-ребенок не содержит текстовую часть, то текстовая часть берется из ближайшего родителя. Блоки и поля ребенка наследуются от родителя, если в них указаны элементы ‘<Наследуемые блоки>’ и ‘<Наследуемые поля>’. В противном случае блоки и поля определяются заново.

При описании шаблона отчета доступны следующие атрибуты:

image-1648803856808.png

По умолчанию используются следующие метки:

Между метками располагается имя блока.

Данный атрибут применяется для шаблонов в формате HTML и TEXT.

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

По умолчанию используются следующие метки:

Между метками располагается имя поля.

Данный атрибут применяется для шаблонов в формате HTML и TEXT.

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

Атрибут может иметь одно из следующих значений:

image-1648803877558.png

Если не указан атрибут ‘Внешний файл отчета’, то вывод сформированного файла осуществляется внутренней интерфейсной программой.

Если же атрибут ‘Внешний файл отчета’ указан, то в зависимости от расширения указанного файла внутренняя интерфейсная программа вызовет ту компоненту, которая в операционной системе назначена для работы с данным типом файлов.

Использование пары символов ‘{‘ и ‘}’ означает переменную ширину поля. Т.е. ширина определяется либо форматом в описании поля, либо  шириной отображаемого значения. Использование же пары символов ‘[‘ и ‘]’ означает, что ширина поля ограничена пространством между этими двумя символами.

Символы ‘<’ и ‘>’ в начале поля указывают на выравнивание значения влево или вправо.

Вывод сформированного файла осуществляется внутренней интерфейсной программой.

Для отображения результата применяется Microsoft WinWord.

Для отображения результата применяется Microsoft WinWord.

Примеры описания текстовой части для шаблонов разных форматов приведены ниже.

Расширение

Программа

xls

Excel

doc

Word

rtf

Word

htm

Internet browser

html

Internet browser

По умолчанию используются следующая последовательность символов: <НАСЛЕДОВАТЬ_ТЕКСТ_ИЗ_ШАБЛОНА_РОДИТЕЛЯ>.

Данный тег применяется для шаблонов в формате HTML и TEXT.

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

Правила описания текстовой части шаблона в формате RTF

Для создания шаблона используется программа WinWord. Шаблон сохраняется в файле формата RTF. При создании изображения шаблона в качестве меток полей и блоков используются стандартные закладки (bookmark) программы WinWord. Имена таких закладок-меток для блоков должны начинаться с символов BLOCK (например, BLOCKЗаголовок). Метка блока ставится непосредственно перед тем текстом, который должен быть включен в блок. Если в блок должна быть включена строка таблицы, то метка блока должна предшествовать ей, т.е. ставиться непосредственно после завершающей границы предыдущей строки (если такая есть).

В следующем примере метки блоков и полей, которые не видны при обычном просмотре, для наглядности помечены символами <bkmk>:

<bkmk>BLOCKЗаголовок

Документы со строками  за период с <bkmk>Дата_начальная по <bkmk>Дата_начальная

Колонка 1

Колонка 2

Сумма розн.

<bkmk>BLOCKДокумент

Документ №<bkmk>Код  от <bkmk>Дата

<bkmk>BLOCKСтрока

<bkmk>Поле1

<bkmk>Поле2

<bkmk>Сумма

<bkmk>BLOCKИтог_по_документу

Итого по Документу <bkmk>Сумма

<bkmk>BLOCKИтог

Всего <bkmk>Сумма

К блоку «Заголовок» относятся весь текст перед таблицей и верхняя строка таблицы. К блоку «Документ» - вторая строка таблицы. К блоку «Строка» - третья строка таблицы. К блоку «Итог по документу» - четвертая строка таблицы. К блоку «Итог» - весь текст под таблицей.

Так как закладки в документе WinWord не могут содержать пробелов, то вместо них используется символ подчеркивания: ’_’. В структуре отчета не требуется менять названия полей и блоков, поскольку разбор и замена символов производится автоматически.

Правила описания текстовой части шаблона в формате DOT

Для создания шаблона используется программа WinWord. Шаблон сохраняется в файле формата DOT.

В отличие от формата RTF, для описания блоков и полей не используются стандартные закладки (bookmark) программы WinWord. В качестве меток применяются следующие символы:

Метки в таких шаблонах не переопределяются.

Правила описания текстовой части шаблона в формате HTML

Шаблон в формате HTML представляет собой обычный текстовый файл, размеченный тегами HTML. Тег – это управляющий код, заключенный в угловые скобки <…>.

HTML файл отображается специальной программой – броузером HTML файлов.

Броузер распознает теги и формирует изображение текста в соответствии с указанной инструкцией. Для корректного отображения результата шаблон отчета должен быть подготовлен в соответствии с правилами языка HTML. Основные правила формирования текста в формате HTML приведены в Приложении ‘HTML в Домино’.

Кроме тегов в шаблоне обязательно должны быть выделены блоки и поля. Метки блоков и полей задаются в соответствующих атрибутах (‘Метка блока’, ’Метка поля’).

Базовые процедуры для работы с отчетами

В проекте имеются одна специальная функция и четыре процедуры для обработки шаблонов в  скриптах-отчетах.

image-1648803910334.png

image-1648803918015.png

Схема выполнения отчета-скрипта для печати с шаблоном должна содержать следующую последовательность вызовов этих процедур:

При наследовании от базового отчета используется только функция ‘Отчет.Печать блока’.

Отчет.Инициализация

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

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

image-1648803938564.png

Отчет.Печать блока

Процедура печатает указанный блок. Данную процедуру необходимо вызвать хотя бы один раз, поскольку блок – это минимальная единица печати. Без печати блока никакие данные в результат отчета не попадут.

Процедура имеет следующие формальные параметры для вызова:

image-1648803960307.png

Отчет.Показать

Процедура выводит сформированный результат отчета на экран.

Процедура имеет следующие формальные параметры для вызова:

image-1648808256488.png

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

Отчет.Закрыть

Процедура закрывает файл отчета.

Процедура имеет следующие формальные параметры для вызова:

image-1648804007288.png

Рекомендуется удалять файлы при закрытии отчета.

Базовый ‘Скрипт-отчет для печати с одним шаблоном’

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

Поставленная цель достигается за счет того, что в скрипте-наследнике скрыта работа с функциями ‘Отчет.Инициализация’, ‘Отчет.Показать’ и ‘Отчет.Закрыть’. Разделы 'Выполнить действия' и 'Выполнить при завершении' для отчета-наследника просто недоступны.  Зато доступны подстановки виртуальных блоков 'Инициализация', 'Подготовка данных', 'Печать данных' и 'Действия при завершении'. Из указанных блоков, в наследнике, обязательна только подстановка блока 'Печать данных'.

Рассмотрим описание базового скрипта-отчета.

image-1648804026292.png

Описание скрипта содержит три раздела ‘Локальные переменные’, ’Выполнить действия’, ‘Выполнить при завершении’.

От родителя достались определения следующих виртуальных блоков.

image-1648804059279.png

Разберем подробнее раздел ’Выполнить действия’.

image-1648804076561.png

Алгоритм процедуры начинается с вызова двух виртуальных блоков ‘Инициализация’ и ‘Подготовка данных’.

Далее, запускается функция ‘Отчет.Инициализация’, которая создает файл отчета. Если    переменная ‘Маска файла’ имеет значение, то файл создается с указанным именем. В противном случае имя файла автоматически генерируется программой.

В виртуальном блоке ‘Печать данных’ должны находиться вызовы процедуры ‘Отчет.Печать блока’.

Вызов процедуры ‘Отчет.Печать блока’ может находиться только в блоке ‘Печать данных’, поскольку блоки 'Инициализация' и 'Подготовка данных' вызываются до инициализации отчета, а блок 'Действия при завершении' вызывается уже после закрытия отчета.

Если значение переменной ‘Устройство вывода отчета’ равно ‘На экран’, то вызывается процедура ‘Отчет.Показать’.

Теперь посмотрим на блок ‘Выполнить при завершении’.

image-1648804096142.png

Вначале запускается процедура ‘Отчет.Закрыть’. Если значение переменной ‘Устройство вывода отчета’ не равно ‘В файл’, то созданный файл отчета удаляется.

В самом конце вызывается виртуальный блок ‘Действия при завершении’.

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

Далее рассмотрим скрипт-отчет ‘Движение по приходам от поставщика’, который является наследником интересующего нас базового скрипт-отчета.

image-1648804114796.png

В данной процедуре определены три виртуальных блока.

В блоке ‘Инициализация’ заполняется форма с параметрами отчета.

image-1648804132904.png

В блоке ‘Подготовка данных’ заполняется локальная таблица ‘Приходы по поставщику’.

Блок ‘Печать данных’ содержит вызовы процедуры ‘Отчет.Печать блока’ для различных блоков шаблона.

image-1648804148775.png

Автор данного отчета использовал не все возможности, предоставляемые базовым скрипт-отчетом. Не понадобился виртуальный блок ‘Действия при завершении’.

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

 

SQL в ДОМИНО

Данная глава не является учебником по реляционным БД и SQL. Глава предназначена для новичков в области баз данных, в ней на множестве примеров показаны основы SQL и применение SQL в ДОМИНО. Желающие ознакомится с SQL в более полном объеме могут прочитать книгу Мартина Грабера ‘Введение в SQL’, откуда и были взяты примеры и объяснения.

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

Затем следует описание на языке скриптов в Домино. Описание включает картинку и комментарий к ней.

Введение

SQL (Structured Query Language) – структурный язык запросов – предназначен для работы с реляционными базами данных.

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

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

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

Реляционная база данных редко состоит из одной таблицы. При создании нескольких таблиц со связанной информацией можно выполнять более сложные и мощные операции над данными. Таблицы связываются по столбцам. Рассмотрим пример связанных таблиц.

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

Таблица Продавцы

продавец

имя_продавца

город

вознаграждение

1001

Пил

Лондон

0,12

1002

Серес

Сан Хосе

0,13

1004

Мотика

Лондон

0,11

1007

Рифкин

Барселона

0,15

1003

Аксельрод

Нью Йорк

0,10

Таблица Покупатели

покупатель

имя_покупателя

город

рейтинг

продавец

2001

Хофман

Лондон

100

1001

2002

Джованни

Рим

200

1003

2003

Лу

Сан Хосе

200

1002

2004

Грасс

Берлин

300

1002

2006

Клеменс

Лондон

100

1001

2008

Гиснерос

Сан Хосе

300

1007

2007

Перейра

Рим

100

1004

Таблица Заказы

заказ

количество

дата

покупатель

продавец

3001

18,69

10.03.1990

2008

1007

3003

767,19

10.03.1990

2001

1001

3002

1900,10

10.03.1990

2007

1004

3005

5160,45

10.03.1990

2003

1002

3006

1098,16

10.03.1990

2008

1007

3009

1713,23

10.04.1990

2002

1003

3007

75,75

10.04.1990

2004

1002

3008

4723,00

10.05.1990

2006

1001

3010

1309,95

10.06.1990

2004

1002

3011

9891,88

10.06.1990

2006

1001

Три эти таблицы образуют реляционную базу данных. Покажем на её основе основные понятия, связанные с применением SQL.

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

Вот как эти таблицы могут быть описаны в Домино.

image-1648804215863.png

Использование SQL для выборки данных из таблиц. Предложение SELECT

Для поиска информации в базе данных применяются различные виды запросов. Запрос – это команда для системы управления базой данной, которая записана в соответствии с некоторыми формальными правилами. Команда требует от СУБД предоставить определенную указанную информацию.

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

SELECT * | { [DISTINCT | ALL] <список полей> .,…}

            FROM {<имя таблицы> [<алиас>]}…     

                        [WHERE <условие>]

                        [GROUP BY {<имя столбца> <целое>} .,…]

                        [HAVING < условие >]

                        [ORDER BY {<имя столбца> | <целое>} .,…]

[{UNION [ALL]

SELECT * | { [DISTINCT | ALL] <список полей> .,…}

                        FROM {<имя таблицы> [<алиас>]}…     

                                   [WHERE < условие >]

                                   [GROUP BY {<имя столбца> <целое>} .,…]

                                   [HAVING < условие >]

                                   [ORDER BY {<имя столбца> | <целое>} .,…]

}]…;

Символы:

| - Все то, что предшествует данному символу, можно заменить тем, что следует за ним. Аналогично ИЛИ.

{} – Все то, что заключено в фигурные скобки, рассматривается как единое целое для применения других символов (в том числе для символа |).

[] – Все то, что заключено в квадратные скобки, является необязательным.

.,… - Все то, что предшествует этим символам, может повторяться произвольное число раз; каждое отдельное вхождение отделяется запятой.

Выбор чего-либо простейшим способом

В простейшей форме команда SELECT дает инструкцию базе данных для поиска информации в одной таблице. Например, можно получить содержимое таблицы ‘Продавцы’ следующим образом:

SELECT продавец, имя_продавца, город, вознаграждение

FROM Продавцы

Команда просто выводит все данные из таблицы. Получаем:

Продавец

Имя-Продавца

Город

Вознаграждение

1001

Пил

Лондон

0,12

1002

Серес

Сан Хосе

0,13

1004

Мотика

Лондон

0,11

1007

Рифкин

Барселона

0,15

1003

Аксельрод

Нью Йорк

0,10

Стоит отметить, что запрос по своей природе не обязательно упорядочивает данные каким-либо определенным образом. Одна и та же команда, выполненная в различные моменты времени, в результате выдает данные, упорядоченные по-разному. Обычно строки выдаются в том порядке, в котором они представлены в таблице, но этот порядок может быть произвольным. Необязательно, что данные в результате выполнения запроса будут представлены в том порядке, в котором они представлены в таблице. Для упорядочивания данных применяются специальные предложения команды SELECT. Позже будет объяснено, как это сделать.

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

SELECT *

FROM Продавцы

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

Вот как этот запрос выглядит в Домино.

image-1648804243167.png

В Домино аналога символа звездочка нет.

Просмотр только определенных столбцов таблицы

Существует возможность указать только требуемые столбцы. Например, по запросу:

SELECT имя_продавца, вознаграждение

FROM Продавцы

Получаются следующие выходные данные:

Имя_продавца

Вознаграждение

Пил

0,12

Серес

0,13

Мотика

0,11

Рифкин

0,15

Аксельрод

0,10

В Домино запрос описывается вот так. В списке параметров описываются только необходимые поля.

image-1648804261337.png

Перестановка столбцов

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

Например, разместим столбцы таблицы Продавцы в другом порядке:

SELECT город, имя_продавца, вознаграждение, продавец 

FROM Продавцы

Город

Имя_Продавца

Вознаграждение

Продавец

Лондон

Пил

0,12

1001

Сан Хосе

Серес

0,13

1002

Лондон

Мотика

0,11

1004

Барселона

Рифкин

0,15

1007

Нью Йорк

Аксельрод

0,10

1003

В Домино тоже можно поменять столбцы местами, хотя это и не имеет смысла.

image-1648804282035.png

Устранение избыточных данных. Аргумент DISTINCT

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

SELECT Продавец

FROM Заказы

Получаем:

Продавец

1007

1001

1004

1002

1007

1003

1002

1001

1002

1001

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

SELECT DISTINCT Продавец

FROM Заказы

Продавец

1001

1002

1003

1004

1007

DISTINCT отслеживает, какие значения появились в списке выходных данных, и исключает из него записи с дублирующимся набором значений параметров. Это отличный способ исключить избыточные данные. Если таковых нет, то использовать DISTINCT не следует.

DISTINCT можно задать только один раз для данного предложения SELECT. Если извлекается несколько полей, то DISTINCT исключает строки, в которых все выбранные поля идентичны. Строки, в которых некоторые значения одинаковые, а другие – различны, включаются в результат.

Альтернативой DISTINCT является ALL. Этот аргумент имеет противоположное действие. Если в предложении SELECT ни задан ни один из этих аргументов, то считается, что указан ALL.

В Домино имеется соответствующий атрибут у запроса.

image-1648804304165.png

Ограничение выборки. Предложение WHERE

С помощью предложения WHERE задается условие (критерий) для определения тех строк, которые следует включить в состав выходных данных. Условие может быть либо истинным, либо ложным для каждой строки таблицы. Команда извлекает только те строки таблицы, для которых условие имеет истинное значение.

Требуется узнать имена всех продавцов из Лондона.

SELECT имя_продавца, город

FROM Продавцы

WHERE город=Лондон

Имя_продавца

Город

Пил

Лондон

Мотика

Лондон

В Домино у запроса тоже имеется конструкция WHERE.

image-1648804323480.png

Использование булевых операторов внутри WHERE

Булевы операторы связывают одно или несколько значений ‘истина/ложь’ и в результате получают единственное значение ‘истина/ложь’. Стандартные булевы операторы – это AND, OR, NOT.

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

Требуется выбрать всех покупателей из Сан Хосе, чей рейтинг превышает 200.

SELECT *

FROM Покупатели

WHERE город=Сан Хосе AND рейтинг>200

Получаем:

покупатель

имя_покупателя

город

рейтинг

продавец

2008

Гиснерос

Сан Хосе

300

1007

Этот запрос в Домино выглядит следующим образом:

image-1648804344008.png

Если требуется выбрать покупателей, которые либо проживают в Сан Хосе, либо имеют рейтинг превышающий 200, то команда выглядит следующим образом:

SELECT *

FROM Покупатели

WHERE город=Сан Хосе OR рейтинг>200

Результат:

покупатель

имя_покупателя

город

рейтинг

продавец

2003

Лу

Сан Хосе

200

1002

2004

Грасс

Берлин

300

1002

2008

Гиснерос

Сан Хосе

300

1007

В Домино изменим операцию:

image-1648804361958.png

Тот же запрос с использованием NOT. Оператор NOT должен предшествовать булеву выражению, значение которого он должен изменить.

SELECT *

FROM Покупатели

WHERE город=Сан Хосе OR NOT рейтинг>200

Результат:

покупатель

имя_покупателя

город

рейтинг

продавец

2001

Хофман

Лондон

100

1001

2002

Джованни

Рим

200

1003

2003

Лу

Сан Хосе

200

1002

2006

Клеменс

Лондон

100

1001

2008

Гиснерос

Сан Хосе

300

1007

2007

Перейра

Рим

100

1004

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

В Домино для каждой операции надо использовать аналог скобок.

image-1648804382853.png

NOT применяется только к тому булеву выражению, которое непосредственно следует за ним. Для изменения области действия NOT используются скобки.

SELECT * FROM Покупатели WHERE NOT (город=Сан Хосе OR рейтинг>200)

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

покупатель

имя_покупателя

город

рейтинг

продавец

2001

Хофман

Лондон

100

1001

2002

Джованни

Рим

200

1003

2006

Клеменс

Лондон

100

1001

2007

Перейра

Рим

100

1004

В Домино тоже добавим дополнительные скобки:

image-1648804401060.png

Оператор IN внутри WHERE

Специальный оператор IN полностью определяет множество, которому данное значение может принадлежать или не принадлежать.

Если нужно найти всех продавцов из Барселоны или из Лондона, то следует составить следующий запрос:

SELECT *

FROM Продавцы

WHERE город=Барселона OR город=Лондон

Ниже приведен более простой способ с применением IN. Элементы в круглых скобках разделяются запятыми.

SELECT *

FROM Продавцы

WHERE город IN (‘Барселона’, ‘Лондон’)

продавец

имя_продавца

город

вознаграждение

1001

Пил

Лондон

0,12

1004

Мотика

Лондон

0,11

1007

Рифкин

Барселона

0,15

В Домино тоже имеется конструкция IN внутри WHERE, но она применяется в тех случаях, когда множество допустимых значений определяется вложенным запросом. В данном же случае достаточно применить выражение.

image-1648804421941.png

Оператор BETWEEN внутри WHERE

Оператор BETWEEN сходен с IN. Вместо перечисления элементов множества, как это делается в IN, BETWEEN задает границы, в которые должно попасть значение, чтобы условие было истинным. Используется ключевое слово BETWEEN, за которым следует начальное значение, ключевое слово AND и конечное значение.

Следующий запрос позволит извлечь всех продавцов, комиссионные которых имеют величину в диапазоне от 0,10 до 0,12.

SELECT *

FROM Продавцы

WHERE вознаграждение

BETWEEN 0,10 AND 0,12

продавец

имя_продавца

город

вознаграждение

1001

Пил

Лондон

0,12

1004

Мотика

Лондон

0,11

1003

Аксельрод

Нью Йорк

0,10

В Домино вместо BETWEEN используются выражения.

image-1648804444994.png

Оператор LIKE внутри WHERE

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

Для задания подстроки применяются специальные символы:

Можно найти покупателей, фамилии которых начинаются на Г.

SELECT *

FROM Покупатели

WHERE имя_покупателя

LIKE ‘Г%’

покупатель

имя_покупателя

город

рейтинг

продавец

2004

Грасс

Берлин

300

1002

2006

Клеменс

Лондон

100

1001

2008

Гиснерос

Сан Хосе

300

1007

В Домино вместо LIKE используются выражения и функция SQL сервера.

image-1648804464481.png

В данном примере функция возвращает номер позиции, в которой находится буква Г.

Оператор IS NULL внутри WHERE

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

Когда NULL значение сравнивается с любым другим значением в булевых операторах результат всегда будет иметь значение NULL.

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

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

SELECT *

FROM Покупатели

WHERE город IS NOT NULL

Или

SELECT *

FROM Покупатели

WHERE NOT город IS NULL

Поскольку в данном случае NULL значения отсутствуют, то результатом будет вся таблица Покупатели.

В Домино такой запрос легко описывается с помощью выражения.

image-1648804484298.png

Функции агрегирования

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

В Домино описание функций агрегирования находится в библиотеке ‘!Примитивы скриптов’, раздел ‘Структура базы данных’, раздел ‘Функции’.

image-1648804504245.png

Предложение GROUP BY

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

Например, требуется найти наибольший заказ из тех, что получил каждый из продавцов. Можно сделать отдельный запрос на каждого продавца, выбрав MAX(количество) для таблицы ‘Заказы’ для каждого значения поля ‘Продавец’. GROUP BY позволяет объединить все это в одной команде:

SELECT продавец, MAX(количество)

FROM Заказы

GROUP BY продавец

Результат:

Продавец

MAX(количество)

1001

9891,88

1002

5160,45

1003

1713,23

1004

1900,10

1007

1098,16

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

В Домино для описания запроса имеется конструкция GROUP BY.

image-1648804527099.png

Функция MAX применена в выражении, которое находится в списке выходных параметров запроса.

Можно также применять GROUP BY с набором полей. Если необходимо увидеть наибольший заказ, сделанный каждому продавцу на каждую дату, то следует сгруппировать данные таблицы ‘Заказы’ по дате внутри одного и того же поля ‘Продавец’ и применить функцию MAX к каждой группе.

SELECT продавец, дата, MAX(количество)

FROM Заказы

GROUP BY продавец, дата

Результат:

Продавец

Дата

MAX(количество)

1001

10.03.1990

767,19

1001

10.05.1990

4723,00

1001

10.06.1990

9891,88

1002

10.03.1990

5160,45

1002

10.04.1990

75,75

1002

10.06.1990

1309,95

1003

10.04.1990

1713,23

1004

10.03.1990

1900,10

1007

10.03.1990

1098,16

Даты, когда продавец не получал заказов, в результате не представлены.

Вот как выглядит этот запрос в Домино.

image-1648804548222.png

Предложение HAVING

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

SELECT продавец, дата, MAX(количество)

FROM Заказы

WHERE MAX(количество) > 3000

GROUP BY продавец, дата

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

Правильная команда выглядит так:

SELECT продавец, дата, MAX(количество)

FROM Заказы

GROUP BY продавец, дата

HAVING MAX(количество) > 3000

Результат:

Продавец

Дата

MAX(количество)

1001

10.05.1990

4723,00

1001

10.06.1990

9891,88

1002

10.03.1990

5160,45

В Домино применение конструкции HAVING выглядит следующим образом:

image-1648804574474.png

Аргументы HAVING подчиняются тем же правилам, что и аргументы SELECT в команде, использующей GROUP BY, и должны иметь единственное значение для каждой выходной группы.

Следующая команда неверна:

SELECT продавец, MAX(количество)

FROM Заказы

GROUP BY продавец

HAVING дата=10.03.1900

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

Вот правильный вариант этого запроса:

SELECT продавец, MAX(количество)

FROM Заказы

WHERE дата=10.03.1900

GROUP BY продавец

Смысл этого запроса – наибольшие заказы на 10.03.1990.

Посмотрим как этот запрос выглядит в Домино.

image-1648804595179.png

Строки и выражения в списке столбцов предложения SELECT

SQL позволяет вносить простые выражения и константы в список выбранных полей.

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

SELECT продавец, имя_продавца, город, вознаграждение * 100

FROM Продавцы

Получим:

Продавец

Имя_продавца

Город

Вознаграждение*100

1001

Пил

Лондон

12

1002

Серес

Сан Хосе

13

1004

Мотика

Лондон

11

1007

Рифкин

Барселона

15

1003

Аксельрод

Нью Йорк

10

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

image-1648804615334.png

Упорядочение записей

Таблицы являются неупорядоченными множествами, и отобранные из них данные необязательно представляются в какой-либо определенной последовательности. Для упорядочивания результата запроса применяется предложение ORDER BY. При наличии этого предложения записи упорядочиваются в соответствии со значениями одного или нескольких выбранных столбцов. Множество столбцов упорядочиваются один внутри другого, и можно задать возрастающую (ASC) или убывающую (DESC) последовательность сортировки для каждого из столбцов. По умолчанию принята сортировка по возрастанию значений.

Таблица заказов, упорядоченная по номеру заказа, выглядит так:

SELECT *

FROM Заказы

ORDER BY заказ DESC

заказ

количество

дата

покупатель

продавец

3001

18,69

10.03.1990

2008

1007

3006

1098,16

10.03.1990

2008

1007

3002

1900,10

10.03.1990

2007

1004

3008

4723,00

10.05.1990

2006

1001

3011

9891,88

10.06.1990

2006

1001

3007

75,75

10.04.1990

2004

1002

3010

1309,95

10.06.1990

2004

1002

3005

5160,45

10.03.1990

2003

1002

3009

1713,23

10.04.1990

2002

1003

3003

767,19

10.03.1990

2001

1001

В Домино для упорядочивания тоже применяется конструкция ORDER BY.

image-1648804638300.png

Внутри уже произведенного упорядочения по полю ‘Заказ’ можно упорядочить таблицу и по другому столбцу, например ‘Количество’.

SELECT *

FROM Заказы

ORDER BY заказ DESC, количество DESC

заказ

количество

дата

покупатель

продавец

3006

1098,16

10.03.1990

2008

1007

3001

18,69

10.03.1990

2008

1007

3002

1900,10

10.03.1990

2007

1004

3011

9891,88

10.06.1990

2006

1001

3008

4723,00

10.05.1990

2006

1001

3010

1309,95

10.06.1990

2004

1002

3007

75,75

10.04.1990

2004

1002

3005

5160,45

10.03.1990

2003

1002

3009

1713,23

10.04.1990

2002

1003

3003

767,19

10.03.1990

2001

1001

В Домино добавляем еще одну строку в конструкцию ORDER BY.

image-1648804658044.png

Предложение ORDER BY можно использовать совместно с предложение GROUP BY для упорядочения групп. Предложение ORDER BY всегда выполняется последним.

SELECT продавец, дата, MAX(количество)

FROM Заказы

GROUP BY продавец, дата

ORDER BY продавец

Результат:

Продавец

Дата

MAX(количество)

1001

10.03.1990

767,19

1001

10.05.1990

4723,00

1001

10.06.1990

9891,88

1002

10.03.1990

5160,45

1002

10.04.1990

75,75

1002

10.06.1990

1309,95

1003

10.04.1990

1713,23

1004

10.03.1990

1900,10

1007

10.03.1990

1098,16

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

В Домино этот запрос выглядит так:

image-1648804678293.png

Соединение таблиц

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

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

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

SELECT Покупатели.имя_покупателя, Продавцы.имя_продавца, Продавцы.город

FROM Продавцы, Покупатели

WHERE Продавцы.город = Покупатели.город

Результат:

Имя_покупателя

Имя_продавца

Город

Хофман

Пил

Лондон

Клеменс

Пил

Лондон

Лу

Серес

Сан Хосе

Гиснерос

Серес

Сан Хосе

Хофман

Мотика

Лондон

Клеменс

Мотика

Лондон

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

В Домино соединение двух таблиц выглядит вот таким образом.

image-1648804699516.png

Можно посмотреть какие покупатели обслуживаются какими продавцами.

SELECT Покупатели.имя_покупателя, Продавцы.имя_продавца

FROM Покупатели, Продавцы

WHERE Продавцы.продавец = Покупатели.продавец

Имя_Покупателя

Имя_продавца

Хофман

Пил

Джованни

Аксельрод

Лу

Серес

Грасс

Серес

Клеменс

Пил

Гиснерос

Рифкин

Перейра

Мотика

 В Домино такой запрос похож на предыдущий.

image-1648804719098.png

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

SELECT заказ, имя_покупателя, покупатель, продавец

FROM Продавцы, Покупатели, Заказы

WHERE Продавцы.город <> Покупатели.город

AND Заказы.покупатель = Покупатели.покупатель

AND Заказы.продавец = Продавцы.продавец

Заказ

Имя_покупателя

Покупатель

Продавец

3001

Гиснерос

2008

1007

3002

Перейра

2007

1004

3006

Гиснерос

2008

1007

3009

Джованни

2002

1003

3007

Грасс

2004

1002

3010

Грасс

2004

1002

Вот этот запрос в Домино.

image-1648804740614.png

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

В ДОМИНО алиасы реализуются автоматически, т.к. адресация к полям таблиц (подзапросов) осуществляется с помощью уточняющего параметра к ссылке на таблицу из  раздела 'FROM (Таблицы)'.

Рассмотрим пример поиска всех пар покупателей, имеющих одинаковый рейтинг.

SELECT Первая.покупатель, Вторая.покупатель, Первая.рейтинг

FROM Покупатели Первая, Покупатели Вторая

WHERE Первая.рейтинг = Вторая.рейтинг 

Покупатель

Покупатель

Рейтинг

Джованни

Джованни

200

Джованни

Лу

200

Лу

Джованни

200

Лу

Лу

200

Грасс

Грасс

300

Грасс

Гиснерос

300

Клеменс

Хофман

100

Клеменс

Клеменс

100

Клеменс

Перейра

100

Гиснерос

Грасс

300

Гиснерос

Гиснерос

300

Перейра

Хофман

100

Перейра

Клеменс

100

Перейра

Перейра

100

Хофман

Клеменс

100

Хофман

Хофман

100

Хофман

Перейра

100

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

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

SELECT Первая.покупатель, Вторая.покупатель, Первая.рейтинг

FROM Покупатели Первая, Покупатели Вторая

WHERE Первая.рейтинг = Вторая.рейтинг

            AND Первая. покупатель < Вторая. покупатель

Покупатель

Покупатель

Рейтинг

Гиснерос

Грасс

300

Джованни

Лу

200

Клеменс

Хофман

100

Клеменс

Перейра

100

Перейра

Хофман

100

Вот описание этого запроса в Домино.

image-1648804766003.png

Соединения таблиц бывают внутренними (inner join) и внешними (outer join). Внутреннее соединение отбирает только те строки, которые точно удовлетворяют равенству. В предыдущих примерах рассматривалось именно внутреннее соединение. В Домино для указания внутреннего соединения также указывается операция равенства.

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

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

Например

В ДОМИНО для указания внешнего соединения используется специальный атрибут 'Результат (Внешнее соединение таблиц - допустимо отсутствие значения'. Различать правое и левое внешние соединения в ДОМИНО не имеет смысла, а полное внешнее соединение не поддерживается.

Вложенные запросы

SQL позволяет вкладывать запросы друг в друга.

В Домино возможно применение вложенных запросов в выражениях (в этом случае запрос должен возвращать только одно значение), в предложении FROM (в качестве источника данных) или в конструкциях IN и EXISTS.

Предположим, известно имя, но не известно значение поля ‘Продавец’ для продавца Мотика. Необходимо извлечь все ее заказы.

SELECT *

FROM Заказы

WHERE продавец =

            ( SELECT продавец

               FROM Продавцы

               WHERE имя_продавца = ‘Мотика’ )

заказ

количество

дата

покупатель

продавец

3002

1900,10

10.03.1990

2007

1004

Чтобы выполнить внешний (основной) запрос, SQL прежде всего должен выполнить внутренний запрос в предложении WHERE. В результате выбранной оказывается единственная строка с ‘Продавец’ = 1004. SQL подставляет это значение в условие вместо подзапроса: WHERE Продавец = 1004

Затем выполняется основной запрос.

В Домино для описания подзапроса имеется соответствующая конструкция внутри WHERE.

image-1648804806585.png

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

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

В СУБД ORACLE для гарантированного получения единственной записи в предложение WHERE нужно добавить условие (ROWNUM < 2). В ДОМИНО такое условие реализуется с помощью специальной функции ‘Это первая найденная запись запроса’.

image-1648804826468.png

Операторы BETWEEN, LIKE, IS NULL в подзапросах применять нельзя.

При использовании операторов IN, EXISTS, ANY, ALL, SOME (ДОМИНО поддерживает только IN и EXISTS) можно использовать подзапросы, возвращающие несколько значений. IN определяет множество значений, на вхождение в которое проверяется результат выражения.

Предположим, требуется найти все заказы для продавцов из Лондона.

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

SELECT заказ, количество, дата, покупатель, Заказы.продавец

FROM Заказы, Продавцы

WHERE Заказы.продавец = Продавцы.продавец

            AND Продавцы.город = ‘Лондон’

Если для решения этой задачи применить подзапрос с оператором IN, то получим следующий запрос:

SELECT заказ, количество, дата, покупатель, продавец

FROM Заказы

WHERE продавец IN

            ( SELECT продавец 

               FROM Продавцы 

               WHERE город = ‘Лондон’)

Заказ

Количество

Дата

Покупатель

Продавец

3003

767,19

10.03.1990

2001

1001

3002

1900,10

10.03.1990

2007

1004

3008

4723,00

10.05.1990

2006

1001

3011

9891,88

10.06.1990

2006

1001

Второй вариант запроса не только выглядит понятнее, но и выполняется быстрее.

В Домино можно использовать конструкцию IN для вложенного запроса.

image-1648804851156.png

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

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

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

SELECT рейтинг, COUNT (DISTINCT покупатель)

FROM Покупатели

GROUP BY рейтинг

HAVING рейтинг >

            ( SELECT AVG(рейтинг)

              FROM Покупатели

              WHERE город = ‘Сан Хосе’)

Рейтинг

COUNT (DISTINCT покупатель)

300

2

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

В Домино такой запрос выглядит тоже не просто.

image-1648804872269.png

Оператор EXISTS

Оператор EXISTS применяется для проверки условия генерации подзапросом выходных данных.

Оператор EXISTS возвращает значение либо ‘истина’, либо ‘ложь’. Этот оператор можно использовать отдельно в условии или комбинировать его с другими булевыми выражениями с помощью операторов AND, OR и NOT. Используя подзапрос в качестве аргумента, EXISTS оценивает его как истинный, если он генерирует выходные данные. В противном случае запрос оценивается как ложный.

Например, требуется извлечь данные о покупателях в том случае, если один (или более) покупатель живет в Лондоне.

SELECT покупатель, имя_покупателя, город

FROM Покупатели

WHERE EXISTS

            ( SELECT *

               FROM Покупатели

               WHERE город = ‘Лондон’ )

Покупатель

Имя_покупателя

Город

2001

Хофман

Лондон

2002

Джованни

Рим

2003

Лу

Сан Хосе

2004

Грасс

Берлин

2006

Клеменс

Лондон

2008

Гиснерос

Сан Хосе

2007

Перейра

Рим

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

Применение конструкции EXISTS в Домино выглядит вот так.

image-1648804894038.png

В ДОМИНО часто применяются подзапрос внутри конструкции EXISTS, который в конструкции WHERE содержит ссылки на параметры основного запроса.

Предложение UNION

Кроме вложенных запросов, когда один запрос вызывается внутри другого, в SQL имеется еще один способ комбинирования запросов – объединение. Объединения отличаются от подзапросов тем, что любой из двух (или большего числа) запросов не может управлять другим запросом. В объединении все запросы выполняются независимо, но их выходные данные потом объединяются. Объединение результатов множества запросов в один записывается с помощью предложения UINION.

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

SELECT продавец, имя_продавца

FROM Продавцы

WHERE город = ‘Лондон’

UNION

SELECT покупатель, имя_покупателя

FROM Покупатели

WHERE город = ‘Лондон’

Продавец / Покупатель

Имя

1001

Пил

1004

Мотика

2001

Хофман

2006

Клеменс

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

Этот запрос в Домино разбивается на три запроса:

image-1648804917031.png

Использование SQL для ввода, изменения и удаления значений полей. Операторы INSERT, UPDATE, DELETE

Оператор INSERT добавляет новые строки в таблицу, оператор UPDATE меняет значения полей существующих строк, а оператор DELETE удаляет строки из таблицы.

Команды имеют следующий синтаксис:

INSERT INTO <имя таблицы> [(<имя столбца> .,…)]

{VALUES (<список полей>) .,…)} | <запрос>

UPDATE <имя таблицы>

            SET { | } .,… <имя столбца> = <список полей>

            [ WHERE <условие> ]

DELETE  FROM <имя таблицы>

            [ WHERE <условие> ]

Символы:

| - Все то, что предшествует данному символу, можно заменить тем, что следует за ним. Аналогично ИЛИ.

{} – Все то, что заключено в фигурные скобки, рассматривается как единое целое для применения других символов (в том числе для символа |).

[] – Все то, что заключено в квадратные скобки, является необязательным.

.,… - Все то, что предшествует этим символам, может повторяться произвольное число раз; каждое отдельное вхождение отделяется запятой.

Для того чтобы добавить одну строку в таблицу ‘Продавцы’ можно использовать простую форму команды INSERT:

INSERT INTO Продавцы VALUES (1001, ‘Пил’, ‘Лондон’, 0,12)

Данный пример отличается неявным указанием столбцов. Значения записываются в поля создаваемой записи в порядке следования столбцов таким образом, что первое из значений, указанных в списке VALUES, заносится в первый столбец, второе значение – во второй столбец и т.д.

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

INSERT INTO Продавцы (город, продавец, вознаграждение, имя_продавца)

VALUES (‘Лондон’, 1001, 0,12, ‘Пил’)

В Домино требуется точное указание столбца (поля).

image-1648804943303.png

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

INSERT INTO Продавцы_из_Лондона

            SELECT продавец, имя_продавца

                        FROM Продавцы

                        WHERE город = ‘Лондон’

По этой команде все значения, полученные с помощью запроса из таблицы ‘Продавцы’, размещаются в таблице с именем ‘Продавцы_из_Лондона’. До выполнения этой команды таблица ‘Продавцы_из_Лондона’ должна быть создана, и должна иметь два столбца, соответствующих аналогичным столбцам таблицы ‘Продавцы’.

 В Домино для такого запроса применяется другой оператор:

image-1648804963175.png

Можно еще более усложнить команду, применяя подзапрос внутри SELECT. Главное ограничение, которое надо помнить, заключается в том, что в предложении FROM любого подзапроса нельзя ссылаться на таблицу, изменяемую в основной команде.

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

DELETE FROM Продавцы

По этой команде удаляются все записи из таблицы ‘Продавцы’, т.е. таблица становится пустой.

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

DELETE FROM Продавцы

WHERE продавец = 1003

В Домино оператор, выполняющий такие действия, описывается достаточно просто:

image-1648804986775.png

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

Например, требуется изменить рейтинг всех покупателей на 200.

UPDATE  Покупатели SET рейтинг = 200

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

UPDATE  Покупатели

SET рейтинг = 200

WHERE покупатель = 1001

Рейтинг изменится только у покупателя с номером 1001.

В Домино для изменения записей применяется оператор ‘Изменить таблицу’.

image-1648805007095.png

Создание таблиц. Оператор CREATE

Таблицы определяются с помощью команды CREATE TABLE, создающей пустую таблицу – таблицу, не имеющую строк. Данная команда определяет имя таблицы и множество поименованных столбцов в указанном порядке. Для каждого столбца устанавливается тип и размер.

Синтаксис команды:

CREATE TABLE <имя таблицы>

            (<имя столбца> <тип данных> [(<размер>)] .,…)

Пример создания таблицы Продавцы:

CREATE TABLE Продавцы

            ( продавец integer,

               имя_продавца char(40),

               город char(40),

               вознаграждение decimal)

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

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

Когда создается индекс по значениям какого-либо поля таблицы, формируется упорядоченный список значений этого поля. Предположим, таблица ‘Покупатели’ имеет тысячи строк и нужно найти покупателя с номером 14762. Поскольку строки не упорядочены, то программа должна просмотреть всю таблицу, строку за строкой, и выбрать ту строку, в которой значение поля ‘покупатель’ равно 14762. Если бы по полю ‘покупатель’ был организован индекс, то программа могла бы сразу найти в нем значение 14762 и получить информацию о том, как обнаружить нужную строку таблицы. Создание индексов может значительно улучшить выполнение запросов, но управление индексами замедляет время выполнения операций обновления (INSERT, UPDATE и DELETE). Кроме того, сам индекс занимает место в памяти. Следовательно перед созданием индексов следует тщательно проанализировать ситуацию.

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

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

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

image-1648805029670.png

Соответствие SQL предложений и конструкций языка скриптов

SQL предложение

Конструкция языка скриптов

SELECT в целом

Запрос в целом

DISTINCT

Признак ‘Distinct (Исключать дублирующие записи)’

ALL

По умолчанию

FROM {<имя таблицы> [<алиас>]}

Раздел ‘FROM (Таблицы)’

SELECT <список полей>

Разделы ‘Параметры’ и ‘Выражения’

[WHERE <условие>]

Раздел ‘WHERE (Ограничения на отбор данных)’

[GROUP BY {<имя столбца> <целое>} .,…]

Раздел ‘GROUP BY (Группировка)’

[HAVING < условие >]

Раздел ‘HAVING (Ограничения на группы строк заданных разделом GROUP BY)’

[ORDER BY {<имя столбца> | <целое>} .,…]

Раздел ‘ORDER BY (Сортировка)’

UNION [ALL]

Условия объединения запросов в разделе ‘FROM (Таблицы)’

Операторы сравнения и булевы операторы

Атрибуты разделов ‘WHERE’ и ‘HAVING’

IN

 

Для произвольного набора значений

реализуется с помощью выражения.

 

Для результатов подзапроса - атрибут ‘IN (равно какому-либо из …) в разделах ‘WHERE’ и ‘HAVING’

BETWEEN

Реализуется с помощью выражения.

LIKE

Реализуется с помощью выражения и описанных в проекте функций SQL сервера.

IS NULL, NOT NULL

= NULL и  <> NULL

Функции агрегирования: COUNT, SUM, AVG, MAX, MIN

Соответствующие функции в проекте

Соединение таблиц (join)

Внутреннее соединение реализуется через обычное равенство, а для внешнего соединения используется специальный атрибут ‘Результат (Внешнее соединение таблиц – допустимо отсутствие значения’

Алиасы

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

Вложенный запрос (подзапрос)

Атрибут ‘Запрос’ в разделах ‘WHERE’,  ‘HAVING’, ‘FROM (Таблицы)’

EXISTS

Атрибут ‘EXISTS (существует …) в разделах ‘WHERE’ и ‘HAVING’

ANY, ALL, SOME

Реализуются с помощью выражения.

INSERT

Операторы ‘Добавить в таблицу’ и ‘Добавить в таблицу результаты запроса’

DELETE

Оператор ‘Удалить из таблицы’

UPDATE

Оператор ‘Изменить таблицу’

CREATE

Достаточно описания таблицы в проекте. Если таблицы не существует, то будет создана. Если существует, то описание на сервере (поля, индексы) будет приведено в соответствие с описанием в проекте.

HTML в Домино

HTML (Hyper Text Markup Language) – это язык разметки (форматирования) документов. Для того чтобы текстовые файлы могли быть прочитаны программой просмотра (броузером), эти тексты размечают тегами HTML. Тег – это управляющий код, заключенный в угловые скобки <…>.

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

В ДОМИНО один из вариантов отображения результата отчетов заключается в вызове HTML броузера. Для корректного отображения результата шаблон отчета должен быть подготовлен в соответствии с правилами языка HTML.

Теги структуры документа

Документы HTML состоят из двух основных частей: заголовка (HEAD) и тела (BODY). И в заголовке и в теле используются теги. Некоторые теги могут использоваться сами по себе, другие теги должны применяться парами (открывающий и закрывающий теги).

Обычно, структура документа выглядит вот таким образом:

<HTML>

<HEAD>

</HEAD>

<BODY>

</BODY>

</HTML>

Теги названий и заголовков

Теги выделения

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

Обычно броузер преобразует текст и при отображении его на экран игнорирует лишние пробелы, символы табуляции и символы концов строк. Если требуется чтобы текст на экране выглядел точно так, как был введен, то следует воспользоваться тегом PRE.

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

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

Для управления шрифтом документа применяются теги <BASEFONT> и <FONT>.

Теги форматирования

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

Для предотвращения произвольного разрыва текста при переполнении строки окна броузера применяются теги NoBr и WBR.

Документ можно разбить на части разделительными полосами. Такие полосы, проходящие по всей ширине страницы, вставляются тегом <HR>. Этот тег имеет необязательные атрибуты, изменяющие вид полосы.

Стиль текста

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

По существу, задание стиля – это назначение элементов выделения для тела и заголовков разного уровня. Если определить стиль заголовка H1 внутри заголовка документа <HEAD>, то всякий раз, когда будет встречаться пара тегов <H1> и </H1>, все, что расположено между ними, будет отображаться этим стилем.

Можно подключить к документу файл со списком стилей:

Подробнее об этой возможности написано ниже.

Таблица

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

Таблицы состоят из названия таблицы, заголовков столбцов и ячеек. Заполняется таблица горизонтальными рядами – ячейка за ячейкой, слева направо. Заполнение начинается с левого верхнего угла и заканчивается правым нижним. Каждая ячейка должна быть заполнена. Для создания пустых ячеек используются пробелы.

Таблицы, как правило, показываются на экране ‘приподнятыми’ над поверхностью страницы, а ячейки – ‘вдавленными’ в тело таблицы. Окантовкой выделяются только заполненные ячейки.

Структура таблицы:

<TABLE >

<CAPTION> название таблицы </CAPTION>

<TR>

<TH> имя первого столбца </TH> <TH> имя второго столбца </TH>

</TR>

<TR>

<TD> первая ячейка </TD> <TD> вторая ячейка </TD>

</TR> ...

...

</TABLE>

Теги ссылок

Текстовые ссылки позволяют щелчком по выделенному слову или фразе перейти к другому файлу. Эта возможность называется гипертекстом.

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

<A NAME=”имя файла”> и </A> - установка якоря.

<A HREF=”имя метки”> и </A> - текстовая ссылка на другой документ.

<A HREF=”#имя метки”> и </A> - ссылка на метку.

<A HREF=”имя файла#имя метки”> и </A> - ссылка на метку другого документа.

Теги для создания списков

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

Упорядоченные списки задаются парным тегом <OL>, а неупорядоченные – парным тегом <UL>. Оба вида используют для элементов списка тег <LI>.

Списки с подзаголовками – это специальные списки, каждый элемент которых состоит из двух частей. Например, подзаголовок и описание. Перед элементами таких списков не ставятся ни маркеры, ни порядковые  номера. Список открывается тегом <DL>. Перед подзаголовком ставится тег <DT>, а перед описанием ставится тег <DD>.

Встраивание графического рисунка

Графика в текст вставляется с помощью тега <IMG>.

Прочие теги

В документы можно вставлять строки, которые не будут отображаться броузером. Это строки комментариев. Внутри комментариев другие теги использовать нельзя.

<!  текст  > - комментарий.

При наборе документа могут использоваться только буквы, цифры и символы, кроме зарезервированных. Зарезервированные символы HTML применяет для своих целей. Если возникла необходимость вставить в текст документа зарезервированный символ, то вместо него надо вставить его буквенный эквивалент.

Список буквенных эквивалентов зарезервированных символов:

 

&quot

&

&amp

&lt

&gt

неразрывный пробел

&nbsp

Для записи символа, не представленного на клавиатуре, вставляется цифровой эквивалент этого символа. Указываются знаки &# и, следом, код ASCII нужного символа.

Задание цвета

Цвет задается указанием в шестнадцатеричном виде трех его составляющих: красной, зеленой  и синей.

Названия и цифровые эквиваленты наиболее распространенных цветов:

Black (Черный)                                 = #000000     

Navy (Темно-синий)            = #000080

Silver (Серебро)                    = #C0C0C0

Blue (Синий)                        = #0000FF

Maroon (Темно-бордовый)  = #800000

Purple (Фиолетовый)           = #800080

Red (Красный)                     = #FF0000

Fuchsia                                  = #FF00FF    

Green (Зеленый)                   = #008000

Teal                                        = #008080

Lime (Известь)                      = #00FF00

Aqua                                      = #00FFFF

Olive (Оливковый)               = #808000

Gray (Серый)                                    = #808080     

Yellow (Желтый)                  = #FFFF00

White (Белый)                                   = #FFFFFF    

 

Каскадные таблицы стилей (CSS)

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

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

Существует три вида таблиц стилей: Внутренние таблицы стилей, Глобальные таблицы стилей и Связанные таблицы стилей. Внутренние таблицы стилей (Inline Style Sheets) мало чем отличаются от HTML тегов. Глобальные (Global Style Sheets) определяют стиль элементов во всем документе. Связанные (Linked Style Sheets) могут быть использованы для нескольких документов и хранятся во внешнем файле.

Расположение описания стилей в отдельном файле имеет смысл в случае, если планируется применять эти стили к большому количеству документов. Для этого нужно создать обычный текстовый файл, описать с помощью языка CSS необходимые стили, а в коде документов, которые будут использовать стили из этого файла, нужно будет сделать ссылку на него. Делается это с помощью тега <LINK> , располагающегося внутри тега <BODY>.

Первые два параметра этого тега являются зарезервированными именами, требующимися для того, чтобы сообщить броузеру, что на этой страничке будет использоваться CSS. Третий параметр - HREF - указывает на файл, который содержит описания стилей. Этот параметр должен содержать путь к файлу.

Во втором варианте описание стилей располагается внутри тега BODY, в теге <STYLE>

 <STYLE type = ”text/css” > . . . </STYLE>

В этом случае можно использовать указанные стили для элементов, располагающихся в пределах документа. Параметр type = ”text/css” является обязательным и служит для указания броузеру использовать CSS.

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

Самый простой способ присвоения какому-либо элементу определенного стиля выглядит так:

НАЗВАНИЕ_ЭЛЕМЕНТА {свойство: значение;}

Пример:

H1 {font-size: 30pt; color: blue;}

В этом примере всем заголовкам на странице, оформленным тегом H1, присваивается размер шрифта 30 пунктов и синий цвет.

CSS реализует возможность присваивать стили не всем одинаковым элементам страницы, а избирательно - для этого используется параметр CLASS = “имя класса” или идентификатор ID = “имя элемента”, присваивающиеся любому элементу документа.

Рассмотрим эти возможности подробнее.

Параметр CLASS применяется в случае, если необходимо создать одинаковый стиль для нескольких, но не всех элементов документа (одинаковых или разных).

Примеры:

.A1 {font-weight: bold; text-align: center}

Все элементы класса A1 будут отображаться жирным шрифтом с выравниванием по центру страницы (или ячейки таблицы).

<P CLASS="A1">Текст параграфа</P>

<TD CLASS="A1">текст</TD>

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

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

Присвоение стилей с помощью идентификаторов применяется в случае, если данному идентификатору соответствует только один элемент в документе. Если элементов, которым необходимо присвоить такой стиль, несколько - это уже класс.

Язык CSS насчитывает довольно большое количество свойств элементов HTML, которыми он может управлять. Но этот стандарт в полном объеме поддерживают не все броузеры. Совместно с  ДОМИНО рекомендуется использовать Microsoft Internet Explorer версии 5 и выше.

Далее рассмотрим некоторые элементы стиля.

Свойства шрифта

font-family - Используется для указания шрифта или шрифтового семейства, которым будет отображаться элемент.

P {font-family: Times New Roman, sans-serif;}

font-weight - Определяет степень жирности шрифта с помощью трех параметров: lighter, bold, bolder

B {font-weight: bolder;}

font-size - Устанавливает размер шрифта. Параметр может указываться как в относительной (проценты), так и в абсолютной величине (пункты, пикселы, сантиметры)
H1 {font-size: 200%;}
H2 {font-size: 150px;}
H3 {font-size: 400pt;}

Цвет элемента и цвет фона

Color - Определяет цвет элемента

I {color: yellow;}

background-color – Устанавливает цвет фона для элемента – именно для элемента, а не для документа.

<HTML>
<HEAD>
<TITLE>Пример использования CSS</TITLE>

<STYLE type=”text/css”>
H1 {font-size: 300%;}
</STYLE>
</HEAD>

<BODY bgcolor=white>
<center><BR>
<H1 style=”background-color: teal; color: white;”>Cascading</H1>
<H1 style= ”background-color: navy; color: yellow;”>Style</H1>
<H1 style=”background-color: gold; color: brown;”>Sheets</H1>
</BODY>
</HTML>

В этом примере в разделе <STYLE> всем элементам <Н1> был установлен размер 300 % от нормы. Затем каждому из элементов <H1> были присвоены собственные значения цвета фона и цвета символов.

Свойства текста

text-decoration - Устанавливает эффекты оформления шрифта, такие, как подчеркивание или зачеркнутый текст
H4 {text-decoration: underline;}
A {text-decoration: none;}

 text-align - Определяет выравнивание элемента.

P {text-align: justify}
H1 {text-align: center}

text-indent - Устанавливает отступ первой строки текста. Чаще всего используется для создания параграфов с табулированной первой строкой.

P {text-indent: 50pt;}

line-height - Управляет интервалами между строками текста.

P {line-height: 50 %}

Свойства границ

margin-left (margin-right, margin-top) - Устанавливают значения отступов вокруг элемента.

IMG { margin-right: 20pt}
P { margin-left: 2cm}

Единицы измерения

Шаблон отчета ‘Товары по группам по наименованию’

Рассмотрим подробнее пример шаблона отчета. Вот так шаблон выглядит целиком.

{{Заголовок}}

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">

  <link rel=stylesheet href="file:{STYLE}" type="text/css">

</head>

<H1><I>Товары по группам по наименованию.</I></H1>

<table border="0" width="100%" cellspacing="0" cellpadding="0">

<tr>

  <td class="TableHeader" >Код </td>

  <td class="TableHeader" >Наименование </td>

  <td class="TableHeader" >ЕИ </td>

  <td class="TableHeader" >Остаток </td>

  <td class="TableHeader" >Цена розничная </td>

</tr>

{{Группа}}

<tr class=TableLine>

<td align=left> {CODE} </td>

<td align=left>  {NAME} </td>

<td align=right> </td>

<td align=right> </td>

<td align=right> </td>

</tr>

{{Подгруппа}}

<tr class=TableLine>

<td align=left> {CODE} </td>

<td align=left> {NAME} </td>

<td align=right> </td>

<td align=right> </td>

<td align=right> </td>

</tr>

{{Продукт}}

<tr class="TableBody">

<td align=left> {CODE} </td>

<td align=left> {NAME} </td>

<td align=left> {EI} </td>

<td align=right> {STOCK} </td>

<td align=right> {PRICE} </td>

</tr>

{{Итог по подгруппе}}

<tr>

<td colspan=5 class=Total align=left> ИТОГО Продуктов в подгруппе {NAME}: {KOLWO}</td>

</tr>

{{Итог по группе}}

<tr>

<td colspan=5 class=Total align=left> ИТОГО Продуктов в группе {NAME}: {KOLWO}</td>

</tr>

{{Итог}}

</table>

</body></html>

Разобьем текст на элементы.

{{Заголовок}}

Начало блока ‘Заголовок’.

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">

  <link rel=stylesheet href="file:{STYLE}" type="text/css">

</head>

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

<H1><I>Товары по группам по наименованию.</I></H1>

Заголовок первого уровня, выделенный курсивом.

<table border="0" width="100%" cellspacing="0" cellpadding="0">

Задаются атрибуты таблицы. Таблица без рамки на все окно.

<tr>

  <td class="TableHeader" >Код </td>

  <td class="TableHeader" >Наименование </td>

  <td class="TableHeader" >ЕИ </td>

  <td class="TableHeader" >Остаток </td>

  <td class="TableHeader" >Цена розничная </td>

</tr>

Первый ряд ячеек состоит из пяти элементов. Текст в каждой ячейке выделяется одинаковым стилем класса TableHeader.

{{Группа}}

Начало блока ‘Группа’.

<tr class=TableLine>

<td align=left> {CODE} </td>

<td align=left>  {NAME} </td>

<td align=right> </td>

<td align=right> </td>

<td align=right> </td>

</tr>

Второй ряд ячеек отображается стилем класса TableLine. В первую ячейку заносится значение переменной отчета CODE, во вторую – значение переменной NAME. Текст в ячейках выравнивается влево.

{{Подгруппа}}

Начало блока ‘Подгруппа’.

<tr class=TableLine>

<td align=left> {CODE} </td>

<td align=left> {NAME} </td>

<td align=right> </td>

<td align=right> </td>

<td align=right> </td>

</tr>

Этот ряд ячеек заполняется аналогично ячейкам блока ‘Группа’.

{{Продукт}}

Начало блока ‘Продукт’.

<tr class="TableBody">

<td align=left> {CODE} </td>

<td align=left> {NAME} </td>

<td align=left> {EI} </td>

<td align=right> {STOCK} </td>

<td align=right> {PRICE} </td>

</tr>

Ряд ячеек блока ‘Продукт’ отображается стилем класса TableBody. В первую ячейку заносится значение переменной отчета CODE, во вторую – значение переменной NAME, в третью – значение переменной EI. Текст в этих ячейках выравнивается влево. Четвертая ячейка заполняется значением переменной STOCK, пятая - значением переменной PRICE. Поскольку эти переменные числового типа, то применяется выравнивание вправо.

{{Итог по подгруппе}}

Начало блока ‘Итог по подгруппе’.

<tr>

<td colspan=5 class=Total align=left> ИТОГО Продуктов в подгруппе {NAME}: {KOLWO}</td>

</tr>

Все ячейки объединяются в одну. В обобщенной ячейке текст отображается стилем класса Total и выравнивается влево. Высвечивается следующий текст: ‘ИТОГО Продуктов в подгруппе’, значение переменной NAME, далее следует двоеточие (:) и значение переменной KOLWO.

 {{Итог по группе}}

<tr>

<td colspan=5 class=Total align=left> ИТОГО Продуктов в группе {NAME}: {KOLWO}</td>

</tr>

Аналогичное описание для блока ‘Итог по группе’.

{{Итог}}

Начало блока ‘Итог’.

</table>

</body></html>

Конец таблицы и тела документа.

Файл стилей stl_green.css

Рассмотрим подробнее один из файлов стилей, используемых в ДОМИНО.

body {font-family:  Courier;

      font-size: 12pt;

      Background: url(green.bmp)

     }

H1  {font-family: Arial;

             font-size: 14pt;

             font-weight: bold;

             text-align: center

            }

table.MainTable

      {font-family: Courier;

       table-border: 4px;

       margin: none;

       padding: 4px;

       }

th

   {text-align: center;

    font-size: 12pt;

    font-weight: bold;

    color: rgb(255,255,255);

    background-color: rgb(24,56,47);

    border : 1px solid;

    mso-number-format:"\@";

    vertical-align : middle;

   }

td.TableHeader

   {text-align: center;

    font-size: 12pt;

    font-weight: bold;

    color: rgb(255,255,255);

    background-color: rgb(24,56,47);

    border : 1px solid;

    mso-number-format:"\@";

    vertical-align : middle;

   }

tr.TableBody   

   {font-size: 10pt;

    font-family: Arial;

    background-color: rgb(205,215,204);      

    mso-number-format:"\@";

   } 

.TableBodySumma

   {font-size: 10pt;

    font-family: Arial;

    background-color: rgb(205,215,204);      

    mso-number-format:"\#\,\#\#0\.00";

    white-space : nowrap;

   } 

tr.TableLine

   {font-family: Arial;

    font-size: 10pt;

    font-weight: bold;

    background-color: rgb(153,173,152);

   }

td.Total

   {font-family: Arial;

    font-size: 10pt;

    font-weight: bold;

    background-color: rgb(153,173,152);

    border-bottom: 1px solid

   }

Разобьем текст на элементы.

body {font-family:  Courier;

      font-size: 12pt;

      Background: url(green.bmp)

     }

Для тела документа указан стиль со следующими характеристиками: шрифт Courier, размер шрифта 12 пунктов, для отображения фона применяется рисунок, находящийся в файле green.bmp.

H1  {font-family: Arial;

             font-size: 14pt;

             font-weight: bold;

             text-align: center

            }

Для заголовков первого уровня указан следующий стиль: жирный шрифт Arial, размер шрифта 14 пунктов, выравнивание текста по центру.

table.MainTable

      {font-family: Courier;

       table-border: 4px;

       margin: none;

       padding: 4px;

       }

Для таблицы определен стиль класса MainTable. Шрифт Courier, ширина рамки вокруг таблицы (и ячеек) и промежуток  между содержимым ячейки и ее рамкой по 4 пикселя, без отступов.

th

   {text-align: center;

    font-size: 12pt;

    font-weight: bold;

    color: rgb(255,255,255);

    background-color: rgb(24,56,47);

    border : 1px solid;

    mso-number-format:"\@";

    vertical-align : middle;

   }

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

td.TableHeader

   {text-align: center;

    font-size: 12pt;

    font-weight: bold;

    color: rgb(255,255,255);

    background-color: rgb(24,56,47);

    border : 1px solid;

    mso-number-format:"\@";

    vertical-align : middle;

   }

Описание класса TableHeader для ячейки совпадает с описанием стиля для заголовка таблицы.

tr.TableBody   

   {font-size: 10pt;

    font-family: Arial;

    background-color: rgb(205,215,204);      

    mso-number-format:"\@";

   } 

Описание класса TableBody для ряда ячеек: шрифт Arial, размер шрифта 10 пунктов, серо-зеленый цвет фона.

.TableBodySumma

   {font-size: 10pt;

    font-family: Arial;

    background-color: rgb(205,215,204);      

    mso-number-format:"\#\,\#\#0\.00";

    white-space : nowrap;

   } 

Описание класса TableBodySumma почти совпадает с описанием класса TableBody.

tr.TableLine

   {font-family: Arial;

    font-size: 10pt;

    font-weight: bold;

    background-color: rgb(153,173,152);

   }

Описание класса TableLine для ряда ячеек: шрифт Arial, размер шрифта 10 пунктов, жирный шрифт, серо-зеленый цвет фона.

td.Total

   {font-family: Arial;

    font-size: 10pt;

    font-weight: bold;

    background-color: rgb(153,173,152);

    border-bottom: 1px solid

   }

Описание класса Total для ячейки почти совпадает с описанием класса TableLine.