ДИНАМИЧЕСКИЕ ВРЕМЕННЫЕ ТАБЛИЦЫ
Решение отдельных задач требует построения временных таблиц количество столбцов в которых заранее неизвестно. Одним из примеров таких задач является построение таблицы, в которой выводятся остатки по счетам за каждый день заданного периода. Таким образом, в строках подобной таблицы выводятся счета, по которым строится информация, а в столбцах - остатки на счетах за определенный день. Так как период может быть задан произвольно, то и количество столбцов тоже будет произвольным.
Создание структуры динамической таблицы осуществляется поэтапно. Первоначально создается сам объект и указатель таблицы, а после в ней создаются поля и индексы. По завершению создания структуры таблицы она фиксируется, после чего вносить изменения в ее структуру становится невозможным.
СОЗДАНИЕ ТАБЛИЦЫ
Создание временной динамической таблицы осуществляется оператором CREATE TEMP-TABLE:
DEF VAR hTable AS HANDLE NO-UNDO.
CREATE TEMP-TABLE hTable.
Создание таблицы так же возможно на основе иной таблицы с помощью метода CREATE-LIKE, с последующей возможностью дополнить ее своими полями:
hTable:CREATE-LIKE(buf-src-hdl).
где, buf-src-hdl - handle буфера исходной таблицы.
Таким образом, мы создали объект временной таблицы с указателем hTable. Набор атрибутов и методов статических временных таблиц, описанный в статье Временные и рабочие таблицы, применим и к динамическим. При этом, динамические временные таблицы обладают дополнительным набором методов, которые мы рассмотрим ниже. А так же рассмотрим особенности значений отдельных атрибутов.
Атрибуты:
Атрибут | Доступ | Тип данных | Описание |
HAS-RECORDS | Чтение | LOGICAL | Возвращает FALSE, если временная таблица не имеет ни одной записи, или же находится в состоянии UNPREPARED. И соответственно TRUE если таблица имеет хоть одну запись. |
PREPARED | Чтение | LOGICAL | Возвращает TRUE, если таблица находится в состоянии PREPARED и FALSE в состоянии UNPREPARED. |
PRIMARY | Чтение/Запись | СHARACTER | Возвращает и устанавливает PRIMARY индекс таблицы. Возвращает неизвестное значение, если таблица находится в UNPREPARED состоянии. |
Методы:
Метод | Описание |
ADD-NEW-FIELD() | создание нового поля |
ADD-LIKE-FIELD() | добавление поля подобием поля другой таблицы |
ADD-FIELDS-FROM() | добавление полей из другой таблицы |
ADD-NEW-INDEX() | определение индекса |
ADD-LIKE-INDEX() | определение индекса подобием индекса другой таблицы |
ADD-INDEX-FIELD() | определение поле входящих в индекс |
TEMP-TABLE-PREPARE() | завершение создания структуры таблицы |
ДОБАВЛЕНИЕ ПОЛЕЙ
После того как мы объявили таблицу, необходимо определить ее поля.
МЕТОД ADD-NEW-FIELD добавления нового поля в таблицу.
ADD-NEW-FIELD(fld-name, fld-datatype [, extent [, format [, initial [, label [, column-label]]]]] )
- fld-name - имя создаваемого поля, тип CHAR;
- fld-datatype - тип данных поля, тип CHAR;
- extent - размер массива, тип INT64;
- format - формат поля, тип CHAR;
- initial - начальное значение;
- label - метка, тип CHAR;
- column-label -
hTable:ADD-NEW-FIELD("abfield","char",0,,"abc").
МЕТОД ADD-LIKE-FIELD добавления нового поля подобием поля другой таблицы.
ADD-LIKE-FIELD(fld-name, src-buf-fld-hdl | src-db-fld-name)
- fld-name - имя создаваемого поля;
- src-buf-fld-hdl - handle буфера копируемого поля исходной таблицы;
- src-db-fld-name - имя копируемого поля исходной таблицы.
hTable:ADD-LIKE-FIELD("acct","acct.acct").
МЕТОД ADD-FIELDS-FROM копирования полей в таблицу из другой существующей таблицы
ADD-FIELDS-FROM({src-buf-hdl | src-tabl-name}[, excet-fld-list])
- src-buf-hdl - handle буффера таблицы с которой осуществляется копирование полей;
- src-tabl-name - имя таблицы с которой осуществляется копирование полей;
- excet-fld-list - список полей с разделителем запятая, исключаемых при копировании.
hTable:ADD-FIELDS-FROM("person", "birthplace").
ДОБАВЛЕНИЕ ИНДЕКСОВ
Добавление индексов для динамических таблиц состоит из 2-х методов. 1-е это создание самого индекса и 2-е определение полей таблицы входящих в индекс.
МЕТОД ADD-NEW-INDEX добавления индекса в таблицу
ADD-NEW-INDEX(index-name[unique-idx[,primary-idx[,word-idx]]])
- index-name - идентификатор индекса, тип CHAR;
- unique-idx - является ли индекс UNIQUE, тип LOGICAL;
- primary-idx - является ли индекс PRIMARY, тип LOGICAL;
- word-idx - является ли индекс WORD, тип LOGICAL;
hTable:ADD-NEW-INDEX("idx1", TRUE, TRUE).
МЕТОД ADD-INDEX-FIELD указание полей таблицы составляющих индекс
ADD-INDEX-FIELD(index-name, field-name [, mode])
- index-name - идентификатор индекса для которого определяется поле, тип CHAR;
- field-name - идентификатор добавляемого поля, тип CHAR;
- mode - определяет сортировку по добавляемому полю ("desc" - descending, или "asc" - ascending), тип CHAR.
hTable:ADD-INDEX-FIELD("idx1", "field1").
hTable:ADD-INDEX-FIELD("idx1", "field2", "desc").
МЕТОД ADD-LIKE-INDEX
ADD-LIKE-INDEX(index-name, source-index-name {, source-buffer-handle | source-db-table-name})
- index-name - идентификатор индекса, тип CHAR;
- source-index-name - идентификатор копируемого индекса, тип CHAR;
- source-buffer-handle - идентификатор буфера таблицы, в котором определен копируемый индекс, тип CHAR;
- source-db-table-name - идентификатор таблицы, в которой определен копируемый индекс, тип CHAR.
ЗАВЕРШЕНИЕ ОБЪЯВЛЕНИЯ ТАБЛИЦЫ
После добавления всех полей и индексов в структуру таблицы, необходимо ее зафиксировать с помощью метода TEMP-TABLE-PREPARE.
TEMP-TABLE-PREPARE( temp-table-name)
- temp-table-name - идентификатор таблицы для использования в QUERY, тип CHAR.
hTable:TEMP-TABLE-PREPARE("ordx").
После применения метода TEMP-TABLE-PREPARE добавить поле или индекс в структуру таблицы - невозможно.
ПРИМЕР РАБОТЫ С ДИНАМИЧЕСКИМИ ТАБЛИЦАМИ
{globals.i}
{tmprecid.def}
{getdates.i}
{sh-defs.i}
DEF VAR hTable AS HANDLE NO-UNDO.
DEF VAR hDefBuffer AS HANDLE NO-UNDO.
DEF VAR hQuery AS HANDLE NO-UNDO.
DEF VAR hField AS HANDLE NO-UNDO.
DEF VAR iDate AS DATE NO-UNDO.
DEF VAR chDate AS CHAR NO-UNDO.
DEF VAR vNumFlds AS INT64 NO-UNDO.
DEF VAR vIndex AS INT64 NO-UNDO.
/* ========== Создание структуры динамической таблицы ========== */
CREATE TEMP-TABLE hTable.
hTable:ADD-NEW-FIELD("acct","char",0).
DO iDate = beg-date TO end-date:
chDate = STRING(iDate,"99-99-9999").
hTable:ADD-NEW-FIELD(chDate,"char",0).
END.
hTable:TEMP-TABLE-PREPARE("dynTT").
/* ============================================================= */
hDefBuffer = hTable:DEFAULT-BUFFER-HANDLE.
vNumFlds = hDefBuffer:NUM-FIELDS.
/* =============== Заполнение таблицы данными ================== */
FOR EACH tmprecid,
FIRST acct WHERE RECID(acct) EQ tmprecid.id:
hDefBuffer:BUFFER-CREATE.
/* -------------------- Счет ------------------ */
/* получение хэндла поля по его имени */
hField = hDefBuffer:BUFFER-FIELD("acct").
/* ввод значения поля */
hField:BUFFER-VALUE() = DelFilFromAcct(acct.acct).
/* ------------------ Остатки ----------------- */
iDate = beg-date.
REPEAT vIndex = 2 TO vNumFlds:
/* получение хэндла поля по его номеру */
hField = hDefBuffer:BUFFER-FIELD(vIndex).
RUN acct-pos IN h_base(acct.acct,
acct.currency,
iDate,
iDate,
CHR(251)).
iDate = iDate + 1.
hField:BUFFER-VALUE() = sh-in-bal.
END.
END.
/* ============================================================= */
/* ==================== Вывод данных таблицы =================== */
/* Создание запроса */
CREATE QUERY hQuery.
hQuery:SET-BUFFERS(hDefBuffer).
hQuery:QUERY-PREPARE("FOR EACH dynTT").
hQuery:QUERY-OPEN().
{setdest.i}
/* ------------------- Шапка отчета ---------------------*/
PUT UNFORMATTED "Счет" FORMAT "x(20)" SPACE(1).
REPEAT vIndex = 2 TO vNumFlds:
hField = hDefBuffer:BUFFER-FIELD(vIndex).
PUT UNFORMATTED hField:LABEL FORMAT "x(15)" SPACE(1).
END.
PUT UNFORMATTED SKIP(1).
/* -------------------- Тело отчета -------------------- */
REPEAT:
hQuery:GET-NEXT().
IF hQuery:QUERY-OFF-END THEN LEAVE.
/* Пробег по полям строки */
/* Счет */
hField = hDefBuffer:BUFFER-FIELD("acct").
PUT UNFORMATTED hField:BUFFER-VALUE() FORMAT "x(20)" SPACE(1).
/* Остатки */
REPEAT vIndex = 2 TO vNumFlds:
hField = hDefBuffer:BUFFER-FIELD(vIndex).
PUT UNFORMATTED hField:BUFFER-VALUE() FORMAT "x(15)" SPACE(1).
END.
PUT UNFORMATTED SKIP.
END.
{preview.i}
hQuery:QUERY-CLOSE().
hDefBuffer:BUFFER-RELEASE().
DELETE OBJECT hTable.
DELETE OBJECT hQuery.