ДИНАМИЧЕСКИЕ ВРЕМЕННЫЕ ТАБЛИЦЫ

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

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


СОЗДАНИЕ ТАБЛИЦЫ


Создание временной динамической таблицы осуществляется оператором 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.
Вы здесь: Главная Основы ABL ДИНАМИЧЕСКИЕ ВРЕМЕННЫЕ ТАБЛИЦЫ